fgets() 从一行中读取并存储一个字符两次
fgets() reads and stores a char form a line twice
所以我有一个文件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
你所经历的绝对是意料之中的。关键的误解是您期望 arr[N]
保留第 (N+1)th 个整数,因为它是一个整数数组……但事实并非如此。它是一个字符数组。
如果您将整数存储在 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' | '[=10=]' |
--------------------------------------------------------------------------------------------
所有数字都在同一个数组中,并以 space 分隔。字符串由字符串终止符 '[=19=]'
.
结束
有趣的是,如果你用 printf("%s\n", arr)
打印整个字符串,你会得到
17 12 5 4 16
但是如果你尝试打印传递第二个字符的地址,使用 printf("%s\n", &arr[1])
你会得到
7 12 5 4 16
等等。这意味着 C 不知道(还不知道)您打算存储 5 个整数。在找到字符串终止符之前,字符串是一个(space 不会终止字符串),所以从第二个数字开始只会让 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
可以用于re-entrant 函数是必需的)并且我使用简单的 atoi()
得到了整数(只是因为输入格式是 _under 控制的——我建议使用 strtol()
来更好地控制输入)。
所以我有一个文件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
你所经历的绝对是意料之中的。关键的误解是您期望 arr[N]
保留第 (N+1)th 个整数,因为它是一个整数数组……但事实并非如此。它是一个字符数组。
如果您将整数存储在 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' | '[=10=]' |
--------------------------------------------------------------------------------------------
所有数字都在同一个数组中,并以 space 分隔。字符串由字符串终止符 '[=19=]'
.
有趣的是,如果你用 printf("%s\n", arr)
打印整个字符串,你会得到
17 12 5 4 16
但是如果你尝试打印传递第二个字符的地址,使用 printf("%s\n", &arr[1])
你会得到
7 12 5 4 16
等等。这意味着 C 不知道(还不知道)您打算存储 5 个整数。在找到字符串终止符之前,字符串是一个(space 不会终止字符串),所以从第二个数字开始只会让 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
可以用于re-entrant 函数是必需的)并且我使用简单的 atoi()
得到了整数(只是因为输入格式是 _under 控制的——我建议使用 strtol()
来更好地控制输入)。