fgets 在仅传递空格时给我一个段错误
fgets giving me a segfault when passing only spaces
我正在尝试制作一个 shell,我要注意的条件之一是用户输入一堆 space 时。但是,当我在终端中输入任意数量的 space 时,我从 fgets 得到了一个段错误。它可以是一个 space,也可以是一大堆后跟一个随机字符。我不断遇到段错误。
发展:
我注意到当我删除我的 tokenize 函数时,我没有遇到段错误。为什么会这样?
这是我的代码:
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
/* Initialize variables and methods */
int status;
int i;
int one_nonspace = -1;
int on = 1;
char input[101];
char temp[101];
char* tokenized;
char operators[3] = {'>', '<', '|'};
char** tokens;
void getInput(char *prmpt, char *buff){
printf(">:");
fgets(buff, 101, stdin); //segfault here when input spaces.
/*printf("works!");*/
if(one_nonspace != -1){
printf("spaces");
memcpy( temp, &buff[i], (101-i) );
temp[100] = '[=10=]';
}
if(buff[strlen(buff) -1] != '\n'){
int over = 0;
while(fgetc(stdin) != '\n')
over++;
if(over>0)
{
printf("Command is over 100 characters. Please try again\n");
status = 1;
}
}
else{
buff[strlen(buff) - 1] = '[=10=]';
status = 0;
}
}
char** tokenize(char* a_str)
{
char** result = 0;
size_t count = 0;
char* tmp = a_str;
char* last = 0;
char delim[2];
delim[0] = ' ';
delim[1] = 0;
/* Count how many elements will be extracted. */
while (*tmp)
{
if (' ' == *tmp)
{
count++;
last = tmp;
}
tmp++;
}
/* Add space for trailing token. */
count += last < (a_str + strlen(a_str) - 1);
/* Add space for terminating null string so caller
knows where the list of returned strings ends. */
count++;
result = malloc(sizeof(char*) * count);
if (result)
{
size_t idx = 0;
char* token = strtok(a_str, delim);
while (token)
{
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delim);
}
assert(idx == count - 1);
*(result + idx) = 0;
}
return result;
}
/* Create a parser Feb 2*/
int main(int argc, char **argv){
while(on){
getInput(">: ", input);
tokenized = input;
if(status == 0){
/*printf("%s\n", input);*/
}
/*Split the line into tokens*/
if(input[0] != ' ')
tokens = tokenize(tokenized);
/*if tokens[0] == 'exit', then quit.
*/
if(strcmp(*(tokens),"exit") == 0){
break;}
/*2/3 Now we need to do something with the split up tokens*/
/*printf("input after token: %s\n", input);*/
/*Free the tokens at the end!!! Remember this!*/
if (tokens)
{
int i;
for (i = 0; *(tokens + i); i++)
{
printf("%s\n", *(tokens + i));
free(*(tokens + i));
}
free(tokens);
}
}
return 0;
}
这是问题所在:
/*Split the line into tokens*/
if(input[0] != ' ')
tokens = tokenize(tokenized);
/*if tokens[0] == 'exit', then quit.
*/
if(strcmp(*(tokens),"exit") == 0){
break;}
当输入以 space 字符开头时,您将跳过标记化函数并尝试取消引用 tokens
- NULL 指针。
编辑:您正在尝试使用 print 语句进行调试,这是一种有效的方法,但请记住刷新缓冲区,否则如果在有任何输出之前发生崩溃,您将无法准确了解问题出在哪里.您可以使用 fflush
显式刷新它们,或者如果您在终端上,则只需使用换行符,因为它们通常是行缓冲的。
我正在尝试制作一个 shell,我要注意的条件之一是用户输入一堆 space 时。但是,当我在终端中输入任意数量的 space 时,我从 fgets 得到了一个段错误。它可以是一个 space,也可以是一大堆后跟一个随机字符。我不断遇到段错误。
发展: 我注意到当我删除我的 tokenize 函数时,我没有遇到段错误。为什么会这样?
这是我的代码:
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
/* Initialize variables and methods */
int status;
int i;
int one_nonspace = -1;
int on = 1;
char input[101];
char temp[101];
char* tokenized;
char operators[3] = {'>', '<', '|'};
char** tokens;
void getInput(char *prmpt, char *buff){
printf(">:");
fgets(buff, 101, stdin); //segfault here when input spaces.
/*printf("works!");*/
if(one_nonspace != -1){
printf("spaces");
memcpy( temp, &buff[i], (101-i) );
temp[100] = '[=10=]';
}
if(buff[strlen(buff) -1] != '\n'){
int over = 0;
while(fgetc(stdin) != '\n')
over++;
if(over>0)
{
printf("Command is over 100 characters. Please try again\n");
status = 1;
}
}
else{
buff[strlen(buff) - 1] = '[=10=]';
status = 0;
}
}
char** tokenize(char* a_str)
{
char** result = 0;
size_t count = 0;
char* tmp = a_str;
char* last = 0;
char delim[2];
delim[0] = ' ';
delim[1] = 0;
/* Count how many elements will be extracted. */
while (*tmp)
{
if (' ' == *tmp)
{
count++;
last = tmp;
}
tmp++;
}
/* Add space for trailing token. */
count += last < (a_str + strlen(a_str) - 1);
/* Add space for terminating null string so caller
knows where the list of returned strings ends. */
count++;
result = malloc(sizeof(char*) * count);
if (result)
{
size_t idx = 0;
char* token = strtok(a_str, delim);
while (token)
{
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delim);
}
assert(idx == count - 1);
*(result + idx) = 0;
}
return result;
}
/* Create a parser Feb 2*/
int main(int argc, char **argv){
while(on){
getInput(">: ", input);
tokenized = input;
if(status == 0){
/*printf("%s\n", input);*/
}
/*Split the line into tokens*/
if(input[0] != ' ')
tokens = tokenize(tokenized);
/*if tokens[0] == 'exit', then quit.
*/
if(strcmp(*(tokens),"exit") == 0){
break;}
/*2/3 Now we need to do something with the split up tokens*/
/*printf("input after token: %s\n", input);*/
/*Free the tokens at the end!!! Remember this!*/
if (tokens)
{
int i;
for (i = 0; *(tokens + i); i++)
{
printf("%s\n", *(tokens + i));
free(*(tokens + i));
}
free(tokens);
}
}
return 0;
}
这是问题所在:
/*Split the line into tokens*/
if(input[0] != ' ')
tokens = tokenize(tokenized);
/*if tokens[0] == 'exit', then quit.
*/
if(strcmp(*(tokens),"exit") == 0){
break;}
当输入以 space 字符开头时,您将跳过标记化函数并尝试取消引用 tokens
- NULL 指针。
编辑:您正在尝试使用 print 语句进行调试,这是一种有效的方法,但请记住刷新缓冲区,否则如果在有任何输出之前发生崩溃,您将无法准确了解问题出在哪里.您可以使用 fflush
显式刷新它们,或者如果您在终端上,则只需使用换行符,因为它们通常是行缓冲的。