首页 > 解决方案 > fgets() 从一行中读取并存储一个字符两次

问题描述

所以我有一个文件data.txt,其中写入了随机整数,例如"17 12 5 4 16".

所以,我曾经fgets()读取这行整数并将其存储在char str []. 正如预期的那样str [0] == 17,但是str [1] == 7,依此类推……整数每 2 位存储在数组中的一个元素中,但第二位也存储在后面的元素中。

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

可以做些什么来解决这个问题?

这是我非常典型的代码:

    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);

这是我的整个代码

#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]);

输入:data.txt

标签: cstringinteger

解决方案


你所经历的一切都是意料之中的。关键的误解是您希望arr[N]保存第 (N+1)整数,因为它是一个整数数组……但事实并非如此。它是一个字符数组。

如果将整数存储在char数组中,则每个数字都将占据一个数组位置。所以arr[0]将包含第一个数字的最高有效位和arr[a]最低有效位。

因此,在您的示例中,字符串"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' |
--------------------------------------------------------------------------------------------

所有数字都在同一个数组中,并用空格分隔。字符串由字符串终止符关闭'\0'

有趣的是,如果你打印整个字符串,printf("%s\n", arr)你会得到

17 12 5 4 16

但是如果你尝试打印传递第二个字符的地址,printf("%s\n", &arr[1])你会得到

7 12 5 4 16

等等。这意味着C 不知道(还不知道)您的意图是存储 5 个整数。在找到字符串终止符之前,字符串是一个(空格不会终止字符串),所以从第二个数字开始只会让 C 打印除第一个数字之外的所有字符串。


由于您有一个以众所周知的方式格式化的字符串并且您想要一个整数数组,因此您必须对其进行解析以获取整数:

#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;
}

在我的演示示例中,输入字符串是一个全局数组,而不是像在您的场景中那样从文件中读取的内容,我使用了strtok()strtok_r可以在需要重入函数的情况下使用)并且我得到了整数使用简单atoi()(只是因为输入格式是_under control - 我建议使用strtol()它来更好地控制输入)。


推荐阅读