使用 gets() 按空格分隔字符串
Separating Strings by Spaces Using gets()
今天我有一个关于使用 gets() 函数用空格分隔字符串的问题。我有一个接受用户输入并按字母顺序排序的程序。我的问题出在 main 函数中,我在其中接收字符串。如果遇到行首的单个点或 EOF,程序应停止读取用户输入和 return 排序的链表。我正在使用 gets() 因为它是项目要求的一部分,但是我的问题是当我使用 gets 时它只是将整个字符串发送到我的排序函数而不是用空格分隔它。我的问题是:有没有办法用空格分隔 gets() 捕获的字符串?请在下面找到我的实现以及示例输入。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//defining node structure
typedef struct node
{
char data[255];//can store upto 255 characters
struct node *next;
}Node;
Node *head=NULL;//initially linked list is empty
//method to insert in sorted order
void insert_dictionary_order(char *a)
{
Node *n = (Node*)malloc(sizeof(Node));//creating new node
strcpy(n->data,a);//reading data
n->next=NULL;
Node *temp=head,*prev=NULL;
if(temp==NULL)
{
head=n;
}
else
{//inserting in right position
while(temp!=NULL)
{
if(0<strcmp(temp->data,a))
break;
prev=temp;
temp=temp->next;
}
if(prev==NULL)
{
n->next=head;
head=n;
}
else
{
n->next=prev->next;
prev->next=n;
}
}
}
//method to print all words in list
void print_list()
{
Node *temp=head;
while(temp!=NULL)
{
printf("%s ",temp->data);
temp=temp->next;
}
printf("\n");
}
int main()
{
printf("Enter words seperated by spaces:(. or EOF to stop):\n");
do
{
char s[255];
//scanf("%s",s);
gets(s);
if(strcmp(s,".")==0 || strcmp(s,"EOF")==0)
{
insert_dictionary_order(s);//adding to list
break;
}
else
{
while((strcmp(s,'[=10=]') !=0) && (strcmp(s,' ') !=0))
{
insert_dictionary_order(s);//adding to list
}
}
}
while(1);
//printf("The string: %s\n", s);
//now printing list
print_list();
return 0;
}
This is a sample text.
The file will be terminated by a single dot: .
The program continues processing the lines because the dot (.)
did not appear at the beginning.
. even though this line starts with a dot, it is not a single dot.
The program stops processing lines right here.
.
You won't be able to feed any more lines to the program.
编辑:也允许使用 sscanf,但不允许使用 scanf
首先,一些其他的东西。
Don't use gets
。让我们使用 fgets
。一切都会一样,只是更安全。
您不应该使用全局 head
。应将指向字典的指针传递给函数。我不打算在这里更正。
strcpy(n->data,a)
不安全,你不知道a
有多大。与其拥有浪费的静态缓冲区,不如存储 char *
并使用 strdup
复制和分配所需的内存。
typedef struct node
{
char *data;
struct node *next;
} Node;
Node *n = malloc(sizeof(Node));
n->data = strdup(word);
strcmp
比较整个字符串,因此 strcmp(s,".")==0
仅当 s
恰好是一个点时才会匹配。 strcmp(s,'[=23=]')
和 strcmp(s,' ')
都不起作用,因为它们是单个字符,而不是字符串。编译器可以就此向您发出警告,但不幸的是它们在默认情况下处于关闭状态。打开它们。
strcmp(s,"EOF")==0
正在寻找字符串 EOF
。这不是您检测文件结尾的方式。相反,请使用 feof(stdin)
检查您是否已到达文件末尾。
但是,checking for EOF is unnecessary 并会引起错误。正常的 fgets
循环是这样的:
// Allocate a large buffer and reuse it.
char line[BUFSIZ];
// `fgets` returns NULL on error or end-of-file, which is false.
while( fgets(line, sizeof(line), stdin) ) {
// Put processing the line into a function to keep things simple.
if( add_line(line) ) {
// We saw a dot, exit the loop.
break;
}
}
Is there a way to separate the string captured by gets() by white spaces?
读取行后,我们可以使用 strtok
(STRing TOKenize) 拆分行。 strtok
是一个有趣的函数,它有自己的内部状态。第一次调用时,它会记住调用的内容。然后用 NULL
调用它以继续在字符串中查找更多标记。
strtok
通过将分隔符替换为空字节来工作,这样您就可以读取每个标记而无需复制它。它确实修改了原始字符串,但是我们不关心line
是否被修改了。
bool add_line(char *line) {
char *token;
for(
token = strtok(line, " \t\n"); // split on spaces or tabs
token; // stop when there's nothing more
token = strtok(NULL, " \t\n") // continue splitting line
) {
printf("token: %s\n", token);
if( strcmp(token, ".") == 0 ) {
// We saw a lone dot, stop reading.
return true;
}
insert_dictionary_order(token);
}
// Continue reading.
return false;
}
在 space 和换行符上拆分很重要,否则换行符将成为每个标记的一部分。这会弄乱字典,并且行尾的点将是 ".\n"
而不是匹配。
今天我有一个关于使用 gets() 函数用空格分隔字符串的问题。我有一个接受用户输入并按字母顺序排序的程序。我的问题出在 main 函数中,我在其中接收字符串。如果遇到行首的单个点或 EOF,程序应停止读取用户输入和 return 排序的链表。我正在使用 gets() 因为它是项目要求的一部分,但是我的问题是当我使用 gets 时它只是将整个字符串发送到我的排序函数而不是用空格分隔它。我的问题是:有没有办法用空格分隔 gets() 捕获的字符串?请在下面找到我的实现以及示例输入。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//defining node structure
typedef struct node
{
char data[255];//can store upto 255 characters
struct node *next;
}Node;
Node *head=NULL;//initially linked list is empty
//method to insert in sorted order
void insert_dictionary_order(char *a)
{
Node *n = (Node*)malloc(sizeof(Node));//creating new node
strcpy(n->data,a);//reading data
n->next=NULL;
Node *temp=head,*prev=NULL;
if(temp==NULL)
{
head=n;
}
else
{//inserting in right position
while(temp!=NULL)
{
if(0<strcmp(temp->data,a))
break;
prev=temp;
temp=temp->next;
}
if(prev==NULL)
{
n->next=head;
head=n;
}
else
{
n->next=prev->next;
prev->next=n;
}
}
}
//method to print all words in list
void print_list()
{
Node *temp=head;
while(temp!=NULL)
{
printf("%s ",temp->data);
temp=temp->next;
}
printf("\n");
}
int main()
{
printf("Enter words seperated by spaces:(. or EOF to stop):\n");
do
{
char s[255];
//scanf("%s",s);
gets(s);
if(strcmp(s,".")==0 || strcmp(s,"EOF")==0)
{
insert_dictionary_order(s);//adding to list
break;
}
else
{
while((strcmp(s,'[=10=]') !=0) && (strcmp(s,' ') !=0))
{
insert_dictionary_order(s);//adding to list
}
}
}
while(1);
//printf("The string: %s\n", s);
//now printing list
print_list();
return 0;
}
This is a sample text.
The file will be terminated by a single dot: .
The program continues processing the lines because the dot (.)
did not appear at the beginning.
. even though this line starts with a dot, it is not a single dot.
The program stops processing lines right here.
.
You won't be able to feed any more lines to the program.
编辑:也允许使用 sscanf,但不允许使用 scanf
首先,一些其他的东西。
Don't use gets
。让我们使用 fgets
。一切都会一样,只是更安全。
您不应该使用全局 head
。应将指向字典的指针传递给函数。我不打算在这里更正。
strcpy(n->data,a)
不安全,你不知道a
有多大。与其拥有浪费的静态缓冲区,不如存储 char *
并使用 strdup
复制和分配所需的内存。
typedef struct node
{
char *data;
struct node *next;
} Node;
Node *n = malloc(sizeof(Node));
n->data = strdup(word);
strcmp
比较整个字符串,因此 strcmp(s,".")==0
仅当 s
恰好是一个点时才会匹配。 strcmp(s,'[=23=]')
和 strcmp(s,' ')
都不起作用,因为它们是单个字符,而不是字符串。编译器可以就此向您发出警告,但不幸的是它们在默认情况下处于关闭状态。打开它们。
strcmp(s,"EOF")==0
正在寻找字符串 EOF
。这不是您检测文件结尾的方式。相反,请使用 feof(stdin)
检查您是否已到达文件末尾。
但是,checking for EOF is unnecessary 并会引起错误。正常的 fgets
循环是这样的:
// Allocate a large buffer and reuse it.
char line[BUFSIZ];
// `fgets` returns NULL on error or end-of-file, which is false.
while( fgets(line, sizeof(line), stdin) ) {
// Put processing the line into a function to keep things simple.
if( add_line(line) ) {
// We saw a dot, exit the loop.
break;
}
}
Is there a way to separate the string captured by gets() by white spaces?
读取行后,我们可以使用 strtok
(STRing TOKenize) 拆分行。 strtok
是一个有趣的函数,它有自己的内部状态。第一次调用时,它会记住调用的内容。然后用 NULL
调用它以继续在字符串中查找更多标记。
strtok
通过将分隔符替换为空字节来工作,这样您就可以读取每个标记而无需复制它。它确实修改了原始字符串,但是我们不关心line
是否被修改了。
bool add_line(char *line) {
char *token;
for(
token = strtok(line, " \t\n"); // split on spaces or tabs
token; // stop when there's nothing more
token = strtok(NULL, " \t\n") // continue splitting line
) {
printf("token: %s\n", token);
if( strcmp(token, ".") == 0 ) {
// We saw a lone dot, stop reading.
return true;
}
insert_dictionary_order(token);
}
// Continue reading.
return false;
}
在 space 和换行符上拆分很重要,否则换行符将成为每个标记的一部分。这会弄乱字典,并且行尾的点将是 ".\n"
而不是匹配。