1

I have a txt file that looks like the following:

1:0
2:0
3:1
4:0
...
99:1
100:1

I would like to store the 1s and 0s inside an array (slot[]), (regardless of what's on the left side of the ':'s), but I can't figure out how. Here's a snippet of my code for that:

while((ch=fgetc(fptr)) != EOF) 
{
     if(ch == ':')
     {
       slot[j] = fgetc(fptr);       //saves the character right after ":"into slot[j]?
       j++;
     }
}

I know it's more complicated than this because it doesn't work. I've searched for a long time but can't find it, maybe because I didn't search for the correct terms.

How can I fix this?

Thanks in advance.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
SwanBones
  • 23
  • 6
  • look at strtock function – OldProgrammer Apr 08 '21 at 21:03
  • 1
    What exactly do you want your result to look like? Should slot be a string of "10011..." depending on what is on the right side of the colons? What is your current issue / what behaves differently than you want it to? – JayK Apr 08 '21 at 21:04
  • @JayK id like it to be an array or 100 values, so in this case [0,0,1,0 ... ,1,1] I think its my miscomprehension of the way i have to do it. For now, nothings coming inside the array – SwanBones Apr 08 '21 at 21:06
  • Use `fgets` to read an entire line. Then use `strchr` to find the colon. The character after the colon is the character you seek. – user3386109 Apr 08 '21 at 21:09
  • 1
    Please include the surrounding code, including the declaration and possibly initialization of the slot variable and how you print the result. – JayK Apr 08 '21 at 21:10
  • @JerryJeremiah ah, that explains the 48s, although I don't know how but it does seem to do what I want it to do. Can you explain how that line works? does it work with other values than 1 or 0? – SwanBones Apr 08 '21 at 21:14
  • It puts the numbers 48 and 49 into the array because the character '0' has value 48. If you want 0 and 1 you need `slot[j] = fgetc(fptr) - '0';` But watch out - you don't check that fgetc for errors so if the file ends with `:` there will be problems. Ignoring all that error checking, this works: https://onlinegdb.com/r1pxGgpHO – Jerry Jeremiah Apr 08 '21 at 21:16
  • @JerryJeremiah Ok ill implement that as well. Thanks so much! – SwanBones Apr 08 '21 at 21:21

2 Answers2

2

It seems pretty straight forward with some minor changes, since your specs state that there is always 1 digit on the right and is always 0 or 1, something like this should do it:

if (fptr != NULL)
{
    int ch;
    int j = 0;

    while ((ch = fgetc(fptr)) != EOF)
    {
        if (ch == ':') 
        {
            if ((ch = fgetc(fptr)) != EOF) // get digit after :
            {
                slot[j++] = ch - '0';  // for int array *
                //slot[j++] = ch;      // for char array
            }
            else
            {
                break;
            }
        }
    }
}

Or, for a more robust method using fgets:

if (fptr != NULL)
{
    char temp[100]; // must be large enough to hold the line
    char *ch;
    int j = 0;

    while (fgets(temp, sizeof temp, fptr)) // read whole line
    {
        ch = strchr(temp, ':'); // find :
        if (ch != NULL && (ch[1] == '1' || ch[1] == '0'))
        {
            // add next digit to slot[] if it's 1 or 0
            slot[j++] = ch[1] - '0'; // or remove - '0' for char slot[]
        }
    }
}

Requires string.h header for strchr.

* Check this post if you want to know more about character to digit conversion:

Why is there a need to add a '0' to indexes in order to access array values?

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • @IradOhayon What does that change? – SwanBones Apr 08 '21 at 21:23
  • @anastaciu that works! it fits my needs. If I needed more than one digit, what has to be done? – SwanBones Apr 08 '21 at 21:24
  • @SwanBones, regarding the question of what `+`, its simple character artthmetic using digit encoding to convert characters to ints, check this post for more dtailed explanation https://stackoverflow.com/a/60994407/6865932 – anastaciu Apr 08 '21 at 21:26
  • @SwanBones, deppending on what you are trying to parse the code should be different, lets say you still want 1 and 0 but you have other 1 digit values, then you would need to add `if(ch == '1' || ch == '0')` before you add it to the array. If you had more than 1 digit, then you you need to check the next character, if it's a `\n` then the value is 1 digit, if not, than it might be more, it all deppends on the specific specs you are after. – anastaciu Apr 08 '21 at 21:31
0

The reason it doesn't do what you expect is because you are reading characters and expecting them to be numbers. A character in C has an integer value. The mapping is called ASCII (have an internet search for "ASCII table"). The uppercase alphabet starts at 65, the lower case alphabet starts at 97, and the numeric digits start at 48. So, if '0' is 48 and '1' is 49 you can change '0' and '1' to 0 and 1 respectively by subtracting 48 from each:

slot[j] = fgetc(fptr) - 48;

And that works but later you will forget what 48 means and have to look at an ASCII table again so you should use characters:

slot[j] = fgetc(fptr) - '0';

Which does the same exact thing but makes it obvious why you are subtracting a value.

You can use the same trick to convert upper case to lower case:

if (ch >= 'A' && ch <= 'Z') ch += 32;

Or lower case to upper case:

if (ch >= 'a' && ch <= 'z') ch -= 32;

But of course, there are library functions called tolower() and toupper() which are much more expressive which is why nobody does it that way.

Jerry Jeremiah
  • 9,045
  • 2
  • 23
  • 32