1

I need to read all the information from a line in a file before a space and store it as a string, how do I do that?

File example:

Biology A 4.0
Tennis B 1.0

etc (I need the letter and number later and I know how to store them fine, just the dang string is giving me trouble)

So far I have

int main (void)
{
    FILE* grades;
    char className[10];
    char currChar;
    int i = 0;

    grades = fopen("grades.txt", "r");
    if (fgetc(grades) != ' ')
    {
        currChar = fgetc(grades);
        className[i] = currChar;
        i++;
    } 

    /* what I want to happen here: if a character is not a space, it is
        appended to className. I thought if i was the position in the array,
        I could add in one character at a time
    */
    printf("%s", className); // check to make sure it worked
}

what the result is: the symbol that looks like a ? in a hexagon

Thanks for any help, I'm open to trying other ways too. I tried using fgets with the length i equal to the number of characters before a space found in a previous while loop, but that printed the part directly after the area I wanted.

MariaCodesOK
  • 11
  • 1
  • 1
  • 6
  • 'className is not initialized, adding in a char to one that is uninitialized has no useful outcome. Neither does attempting to printf("%s... an array of chars that is not securely NULL terminated. – Martin James Nov 28 '15 at 05:56
  • 'if (fgetc(grades) != ' '' dumps a char from the input buffer. It is lost. – Martin James Nov 28 '15 at 05:59
  • When dealing with lines of text, try to resist the temptation to declare buffers smaller than, say, [256], (unless you are on a RAM-restricted embedded system). – Martin James Nov 28 '15 at 06:01
  • Just read the char once into your 'currChar', then decide what to do with it. Is it a line-terminator char? Is it a space? – Martin James Nov 28 '15 at 06:03
  • It's just a space. The file given has a bunch of lines that say things like "Biology A 4.0", I want to read in the word "Biology" to "className" – MariaCodesOK Nov 28 '15 at 06:07
  • Also I don't understand what you mean by NULL terminated. Also, why exactly shouldn't I make it smaller than [256]? I know thats 2^8 but the name is only going to be up to 10 characters. I'm not arguing or anything, just wondering – MariaCodesOK Nov 28 '15 at 06:12
  • C 'strings' are just arrays of chars that are terminated with a NULL char. Lacking a length attribute, and without a terminator, calls that handle strings, (like printf("%s..), don't know where the end is. ' the name is only going to be up to 10 characters' - who cares? The C tag is filled with thousands of posts where developers have overrun their little buffers by one byte, (eg. to put in the terminating NULL). Stop counting chars and just declare [256], (or, or course, larger if required), for everything. – Martin James Nov 28 '15 at 06:19
  • Thank you. To null terminate it, I made an else statement else {className[i] = '\0'; return 0;} – MariaCodesOK Nov 28 '15 at 06:25
  • See this:) https://stackoverflow.com/questions/33968927/run-time-check-failure-2-in-c-file-processing – Martin James Nov 28 '15 at 07:46

2 Answers2

3

Why not just use fscanf ?

Something like :

#include <stdio.h>

int main (void)
{
    FILE* grades;
    char className[10];
    char grade;
    float marks = 0;

    grades = fopen("grades.txt", "r");

    while(fscanf(grades,"%s %c %f", className, &grade, &marks)>0) {
        printf("%s %c %f\n", className, grade, marks); 
    }
}
loxxy
  • 12,990
  • 2
  • 25
  • 56
  • Thank you!!! though now I'm angry with myself because I literally thought using something like this earlier fscanf(grades, "%s %c %f", className, letterGrade, credits) but it messed up for whatever reason and you got that to work so thank you thank you – MariaCodesOK Nov 28 '15 at 06:43
  • 1
    the reason was lack of & ... sigh. Also sorry, this is my first post. This is also why the formatting was off before... my programming assignment was saved by (ssj2?) Goku. – MariaCodesOK Nov 28 '15 at 06:51
3

There is nothing wrong with reading from a file up-to the first space character with fgetc, however, there are several problems with:

if (fgetc(grades) != ' ')
{
    currChar = fgetc(grades);
    className[i] = currChar;
    i++;
} 

When you call fgetc(grades) != ' ', a character is read from grades and then the file-position-indicator is advanced to the next character. So when you call fgetc inside the if statement, you read a character and then the file-position-indicator is advanced in preparation for reading the next character. When you then call fgetc again in the body of the if statement (currChar = fgetc(grades);), you read the second character in the file. It seems rather obvious from your question, that your intent was not to skip-a-character and then begin reading with the next.

When you read input with any character-oriented-input function (e.g. getchar, fgetc, etc.) there are three primary things you are responsible for: (1) insuring you do not attempt to write more characters to your storage variable than it will hold; (2) check for any sentinel or terminating character you wish to stop the read with; and (3) checking that you have not reached the end of the input stream.

Putting those pieces together you could do something like:

#include <stdio.h>

#define MAXCN 10

int main (void)
{
    FILE* grades = NULL;            /* initialize variables */
    char className[MAXCN] = {0};
    int currChar = 0;               /* currChar is an int   */
    int i = 0;

    /* open and validate file */
    if ((grades = fopen("grades.txt", "r")) == NULL) {
        fprintf (stderr, "error: file open failed 'grades.txt'.\n");
        return 1;
    }

    /* read from grades until 1st space */
    while (i + 1 < MAXCN && ((currChar = fgetc (grades)) != ' ' && 
                              currChar != EOF)) {
        className[i++] = currChar;
    }
    className[i] = 0;   /* null-terminate */

    printf("\n className: %s\n\n", className);

    return 0;
}

Note: when you stop reading on any character, the next read will resume on the next character in the input stream. So you will need to empty any characters that remain (in the line, etc...) if you want to begin your read at any than other than the next character. Also note, when you open a file with fopen, you should validate that the open actually worked before proceeding to read from the file.

Input

$ cat grades.txt
Homeroom grades are include below

Output

$ ./bin/fgetc_grades

 className: Homeroom

Hopefully this will help you get started, let me know if you have any additional questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Thanks, I used a snippet from above, but in the code shouldn't it be `(currChar = fgetc (grades)) != ' ' && currChar != EOF)`? – Chan Kim Aug 03 '17 at 00:46