简体   繁体   English

fgets() 从一行读取并存储一个字符两次

[英]fgets() reads and stores a char form a line twice

So I have a file data.txt , with random integers written in it, for example "17 12 5 4 16" .所以我有一个文件data.txt ,其中写入了随机整数,例如"17 12 5 4 16"

So, I used fgets() to read this line of integers and store it in a char str [] .因此,我使用fgets()读取这行整数并将其存储在char str [] As expected str [0] == 17 , but str [1] == 7 , an so on... every 2 digits the integer is stored in an element in the array, but the second digit is also stored in the following element.正如预期的那样str [0] == 17 ,但str [1] == 7 ,依此类推......整数每两位数存储在数组中的一个元素中,但第二个数字也存储在以下元素中.

Example: str [3] = 12 , str [4] = 2 , str[5] = ' ' .示例: str [3] = 12str [4] = 2str[5] = ' '

What could be done to fix this issue?可以做些什么来解决这个问题?

Here is my very typical code:这是我非常典型的代码:

    FILE* fp = fopen ("data.txt", "r");

    int i = 0, j = 0;
    int size = fileSize(fp) + 1; // Enumerate the char numbers in file
    char str [size];
    rewind (fp);
    fgets (str, size, fp);

Here is my entire code这是我的全部代码

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

typedef struct RATIONAL
{
    int top;
    int bottom;
} RATIONAL;

void printArray (int arr [], int count)
{
    for (int i = 0; i < count; ++i)
    {
        printf ("%d\n", arr[i]);
    }
}

int fileSize (FILE* fp)
{
    char c;
    int i = 0;
    while ((c = getc (fp)) != EOF)
    {
        i++;
    }
    return (i);
}

int main ()
{
    RATIONAL ratArray [23];  //array to hold rational numbers
    int intArray [45]; //array to hold integer values

    FILE* fp = fopen ("data.txt", "r");

    int i = 0, j = 0;
    int size = fileSize(fp) + 1; // Enumerate the char numbers in file
    char str [size];
    rewind (fp);
    fgets (str, size, fp);

    //Convert string to array of ints
    while (i < size -1)
    {
        if (isdigit (str [i]))
        {
                intArray[j++] = atoi(&str[i]);
                i++;
        }
        else
            i++;
    }
        printArray (intArray, intArray[0]);

Input: data.txt输入: data.txt

What you experience is absolutely expected.您所体验到的绝对是意料之中的。 The key misunderstanding is that you expect arr[N] to hold the (N+1) th integer as it was an array of integers... but it's not.关键的误解是您希望arr[N]保存第 (N+1)整数,因为它是一个整数数组……但事实并非如此。 It is an array of characters.它是一个字符数组。

If you store integers within a char array, every digit will occupy an array location.如果将整数存储在char数组中,则每个数字都将占用一个数组位置。 So arr[0] will contain the most significant digit of the first number and arr[a] the least significant digit.因此arr[0]将包含第一个数字的最高有效数字,而arr[a]将包含最低有效数字。

So, in your example, the string "17 12 5 4 16" will be stored in this way:因此,在您的示例中,字符串"17 12 5 4 16"将以这种方式存储:

--------------------------------------------------------------------------------------------
| 0x31 | 0x37 | 0x20 | 0x31 | 0x32 | 0x20 | 0x35 | 0x20 | 0x34 | 0x20 | 0x31 | 0x36 | 0x00 |
--------------------------------------------------------------------------------------------
|  '1' |  '7' |  ' ' |  '1' |  '2' |  ' ' |  '5' |  ' ' |  '4' |  ' ' |  '1' |  '7' | '\0' |
--------------------------------------------------------------------------------------------

All digits are in the same array and separated by spaces.所有数字都在同一个数组中并用空格分隔。 The string is closed by a string terminator '\\0' .该字符串由字符串终止符'\\0'关闭。

Interesting enough, if you print the whole string with printf("%s\\n", arr) you get有趣的是,如果你用printf("%s\\n", arr)打印整个字符串,你会得到

17 12 5 4 16

but if you try to print passing the address of the second character, with printf("%s\\n", &arr[1]) you get但是如果你尝试打印传递第二个字符的地址,你会得到printf("%s\\n", &arr[1])

7 12 5 4 16

And so on.等等。 This means that C has no idea (not yet) that your intention is to store 5 integers .这意味着C 不知道(还不知道)您的意图是存储 5 个 integers The string is one until the string terminator is found ( the space doesn't terminate the string ), so starting from the second digit will just make C print all the string except the first digit.字符串是一个直到找到字符串终止符(空格不会终止字符串),所以从第二个数字开始只会让 C 打印除第一个数字之外的所有字符串。


Since you have a string formatted in a well known way and you want an array of integers, you have to parse it to get the integers:由于您有一个以众所周知的方式格式化的字符串并且您想要一个整数数组,因此您必须解析它以获取整数:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char arr[] = "7 12 5 4 16";

int main()
{
    char * token = strtok(arr, " ");
    while(token != NULL)
    {
        printf("Next int: %d %s\n", atoi(token)); // Here you can assign the value to your array
        token = strtok(NULL, " ");
    }

    return 0;
}

In my demonstrative example, in which the input string was a global array instead of something read from a file like in your scenario, I used strtok() ( strtok_r can be used in case a re-entrant function is required) and I got the integers using the simple atoi() (just because the input format was _under control - I recommend using strtol() for a better control of the input).在我的演示示例中,输入字符串是一个全局数组,而不是像您的场景中那样从文件中读取的内容,我使用了strtok()strtok_r需要可重入函数,可以使用strtok_r )并且我得到了使用简单的atoi()整数(只是因为输入格式是 _under control - 我建议使用strtol()来更好地控制输入)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM