使用 fgets 读取标准输入,将每一行填充到数组中并打印每一行
Read stdin with fgets, fill each line in an array and print each line
我想用 fgets
阅读 stdin
。
然后,我想读每一行。我的行是用 ' '
分隔的字符串。
例如,这可能是一行:1 2 ab
我认为我应该使用 malloc
来计算我行中的参数数量,因为这个数字可能因行而异。
1 2 3 4
有 4 个,但 a b 2
有 3 个。
我用 strtok
截断了这一行,然后我用 标记 填充了我的 malloc
并打印了它们。
最后的结果就是只打印每一行。
例如,这是一个file.txt:
1 2 33 4
a b1 c
4 b l 11
我也是:
$ cat file.txt | ./a.out
它应该打印:
1 2 33 4
a b1 c
4 b l 11
但事实并非如此!
你们能帮我解决一下吗:O
此外,我想使用数组来计算令牌并在以后使用它们。例如,我需要单独处理每一行的所有第二个参数,所以 array[1].
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv) {
while (fgets(argv, sizeof(argv), stdin) != NULL) {
char *array = (char *)malloc(sizeof(argv));
char *token = strtok(argv, " ");
strtok(token, "\n");
int i = 0;
while (token != NULL) {
array[i] = token;
token = strtok(NULL, " ");
printf("%d\n", array[i]);
++i;
}
}
return 0;
}
如果你只想计算token并输出,那么你可以简单地使用一个指向token的指针,而不需要分配存储空间。使用 strtok()
是个不错的选择。 (注意:如果您有空字段,则需要使用另一种方法进行解析,因为 strtok()
会将顺序分隔符视为单个分隔符)。传递给 strtok()
的字符串必须是可变的,因为 strtok()
会修改字符串(如果需要保留原始字符串,请复制一份)
你的方法是将带有 fgets()
的每一行读入一个足够大的缓冲区(字符数组),将你的计数器归零,然后标记该行,增加每个标记的计数并输出由一个分隔的标记space.
您可以按如下方式进行:
#include <stdio.h>
#include <string.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char line[MAXC]; /* storage for line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (line, MAXC, fp)) {
size_t toks = 0,
len;
line[(len = strcspn (line, "\n"))] = 0; /* trim \n, save length */
for (char *p = strtok (line, " \t"); p; p = strtok (NULL, " \t"))
printf (toks++ ? " %s" : "%s", p);
printf ("%*s\t(%zu tokens)\n", (int)len % 8, " ", toks);
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
}
上面一个三进制用来控制space-分隔符的输出(第一个token之前什么都没有——当计数为零时,然后是一个在每个后续标记之前单个 space)。标记的计数附加到每行的末尾。
(每行的 strlen()
仅用于通过添加制表符的小数部分来整理每个输出行的末尾与附加计数之间的间距,如果需要的话)
例子Use/Output
使用文件 dat/tokfile.txt
中的示例数据,您将收到:
$ ./bin/fgets_tok_count dat/tokfile.txt
1 2 33 4 (4 tokens)
a b1 c (3 tokens)
4 b l 11 (4 tokens)
通过将文件名作为程序的第一个参数,或者如果没有给出参数则默认从 stdin
读取,您也可以将信息重定向到您的程序,例如
$ ./bin/fgets_tok_count < dat/tokfile.txt
否则你的 UUOc 表格也行:
$ cat dat/tokfile.txt | ./bin/fgets_tok_count
每行动态存储未知数量的令牌
要动态存储每个标记并在标记化循环期间保留每个标记,那么您只需要一个指向指针的指针 char
和一个跟踪指针和字符串数量的计数器分配。您可以这样做类似于:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char line[MAXC]; /* storage for line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (line, MAXC, fp)) {
char **tokens = NULL;
size_t len = 0,
toks = 0;
line[(len = strcspn (line, "\n"))] = 0; /* trim \n, save length */
/* loop over each token */
for (char *p = strtok (line, " \t"); p; p = strtok (NULL, " \t")) {
size_t toklen = strlen (p);
/* allocate/validate 1 additional pointer for tokens */
void *tmp = realloc (tokens, (toks + 1) * sizeof *tokens);
if (!tmp) {
perror ("realloc-tokens");
break;
}
tokens = tmp;
/* allocate/validate storage for token of len + 1 */
if (!(tokens[toks] = malloc (toklen + 1))) {
perror ("malloc-tokens[toks]");
break;
}
/* copy token to allocated block */
memcpy (tokens[toks], p, toklen + 1);
toks++; /* increment no. of tokens in line */
}
/* output all stored line tokens and no. of tokens */
for (size_t i = 0; i < toks; i++) {
printf (i ? " %s" : "%s", tokens[i]);
free (tokens[i]); /* done with stored token, free token */
}
free (tokens); /* free pointers */
printf ("%*s\t(%zu tokens)\n", (int)len % 8, " ", toks);
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
}
(程序输出相同)
基本上,上面,realloc
用于每次找到token时为1-additional pointer分配存储空间,然后malloc
用于分配token的长度(+1 ),然后将令牌复制到分配的块中。完成对行的标记后,tokens
指针指向一个包含 toks
指针的内存块,依次分配一个包含每个标记的内存块。在所有标记化和存储完成后,通过遍历指针产生相同的输出,输出标记(和标记数)。然后释放所有内存。
检查一下,如果您还有其他问题,请告诉我。
我想用 fgets
阅读 stdin
。
然后,我想读每一行。我的行是用 ' '
分隔的字符串。
例如,这可能是一行:1 2 ab
我认为我应该使用 malloc
来计算我行中的参数数量,因为这个数字可能因行而异。
1 2 3 4
有 4 个,但 a b 2
有 3 个。
我用 strtok
截断了这一行,然后我用 标记 填充了我的 malloc
并打印了它们。
最后的结果就是只打印每一行。
例如,这是一个file.txt:
1 2 33 4
a b1 c
4 b l 11
我也是:
$ cat file.txt | ./a.out
它应该打印:
1 2 33 4
a b1 c
4 b l 11
但事实并非如此!
你们能帮我解决一下吗:O
此外,我想使用数组来计算令牌并在以后使用它们。例如,我需要单独处理每一行的所有第二个参数,所以 array[1].
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv) {
while (fgets(argv, sizeof(argv), stdin) != NULL) {
char *array = (char *)malloc(sizeof(argv));
char *token = strtok(argv, " ");
strtok(token, "\n");
int i = 0;
while (token != NULL) {
array[i] = token;
token = strtok(NULL, " ");
printf("%d\n", array[i]);
++i;
}
}
return 0;
}
如果你只想计算token并输出,那么你可以简单地使用一个指向token的指针,而不需要分配存储空间。使用 strtok()
是个不错的选择。 (注意:如果您有空字段,则需要使用另一种方法进行解析,因为 strtok()
会将顺序分隔符视为单个分隔符)。传递给 strtok()
的字符串必须是可变的,因为 strtok()
会修改字符串(如果需要保留原始字符串,请复制一份)
你的方法是将带有 fgets()
的每一行读入一个足够大的缓冲区(字符数组),将你的计数器归零,然后标记该行,增加每个标记的计数并输出由一个分隔的标记space.
您可以按如下方式进行:
#include <stdio.h>
#include <string.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char line[MAXC]; /* storage for line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (line, MAXC, fp)) {
size_t toks = 0,
len;
line[(len = strcspn (line, "\n"))] = 0; /* trim \n, save length */
for (char *p = strtok (line, " \t"); p; p = strtok (NULL, " \t"))
printf (toks++ ? " %s" : "%s", p);
printf ("%*s\t(%zu tokens)\n", (int)len % 8, " ", toks);
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
}
上面一个三进制用来控制space-分隔符的输出(第一个token之前什么都没有——当计数为零时,然后是一个在每个后续标记之前单个 space)。标记的计数附加到每行的末尾。
(每行的 strlen()
仅用于通过添加制表符的小数部分来整理每个输出行的末尾与附加计数之间的间距,如果需要的话)
例子Use/Output
使用文件 dat/tokfile.txt
中的示例数据,您将收到:
$ ./bin/fgets_tok_count dat/tokfile.txt
1 2 33 4 (4 tokens)
a b1 c (3 tokens)
4 b l 11 (4 tokens)
通过将文件名作为程序的第一个参数,或者如果没有给出参数则默认从 stdin
读取,您也可以将信息重定向到您的程序,例如
$ ./bin/fgets_tok_count < dat/tokfile.txt
否则你的 UUOc 表格也行:
$ cat dat/tokfile.txt | ./bin/fgets_tok_count
每行动态存储未知数量的令牌
要动态存储每个标记并在标记化循环期间保留每个标记,那么您只需要一个指向指针的指针 char
和一个跟踪指针和字符串数量的计数器分配。您可以这样做类似于:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char line[MAXC]; /* storage for line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (line, MAXC, fp)) {
char **tokens = NULL;
size_t len = 0,
toks = 0;
line[(len = strcspn (line, "\n"))] = 0; /* trim \n, save length */
/* loop over each token */
for (char *p = strtok (line, " \t"); p; p = strtok (NULL, " \t")) {
size_t toklen = strlen (p);
/* allocate/validate 1 additional pointer for tokens */
void *tmp = realloc (tokens, (toks + 1) * sizeof *tokens);
if (!tmp) {
perror ("realloc-tokens");
break;
}
tokens = tmp;
/* allocate/validate storage for token of len + 1 */
if (!(tokens[toks] = malloc (toklen + 1))) {
perror ("malloc-tokens[toks]");
break;
}
/* copy token to allocated block */
memcpy (tokens[toks], p, toklen + 1);
toks++; /* increment no. of tokens in line */
}
/* output all stored line tokens and no. of tokens */
for (size_t i = 0; i < toks; i++) {
printf (i ? " %s" : "%s", tokens[i]);
free (tokens[i]); /* done with stored token, free token */
}
free (tokens); /* free pointers */
printf ("%*s\t(%zu tokens)\n", (int)len % 8, " ", toks);
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
}
(程序输出相同)
基本上,上面,realloc
用于每次找到token时为1-additional pointer分配存储空间,然后malloc
用于分配token的长度(+1 ),然后将令牌复制到分配的块中。完成对行的标记后,tokens
指针指向一个包含 toks
指针的内存块,依次分配一个包含每个标记的内存块。在所有标记化和存储完成后,通过遍历指针产生相同的输出,输出标记(和标记数)。然后释放所有内存。
检查一下,如果您还有其他问题,请告诉我。