C 如何在调用atoi之前将指针设置为NULL

C 如何在调用atoi之前将指针设置为NULL,c,string,C,String,我是C新手,在调用atoi之前,我似乎不知道如何将指针*year设置为NULL。下面的代码将我的字符串分成4个,当我运行它时,它会抛出程序,我确信这是因为我插入了atoi函数。 你能帮帮我吗 char *split(char words[50]) { int i = 0; char* words_dup = malloc(strlen(words)+1); strcpy(words_dup,words); while (words!='\0') { char *word=strto

我是C新手,在调用atoi之前,我似乎不知道如何将指针*year设置为NULL。下面的代码将我的字符串分成4个,当我运行它时,它会抛出程序,我确信这是因为我插入了atoi函数。 你能帮帮我吗

 char *split(char words[50])
 {
int i = 0;
char* words_dup = malloc(strlen(words)+1);
strcpy(words_dup,words);

while (words!='\0')
{
    char *word=strtok(words, "_#_");
    check_word(*word);

    char *year=strtok(NULL, "_#_");;  // assigning NULL for previousely where it left off
    i=atoi(year);
    check_year(i);

    char *definition=strtok(NULL,"_#_");
    check_definition(*definition);

    char *synonyms=strtok(NULL,"_#_");
    check_synonyms(*synonyms);


    printf("%s\t", word);
    printf("%i\t",i);
    printf("%s\t", definition);
    printf("%s\t", synonyms);
}

// now restore words
strcpy(words,words_dup);
free(words_dup);
return 0;
 }

 //------------------------------------------------------------------//
 //                     CHECKING LEGAL OR NOT
 //------------------------------------------------------------------//
 void check_word(char word)
 {
if (word>='A' && word<='Z')
{
    printf("not legal\n");
}
 }


 void check_year(int year)
 {
if (year<0)
{
    printf("not legal\n");
}
 }

 void check_definition(char definition)
 {
if (definition>='A' && definition<='Z')
{
    printf("not legal\n");
}
 }

 void check_synonyms(char synonym)
 {
if (synonym>='a' && synonym<='z')
{
    printf("not legal\n");
}
 }


 int main()
 {
char words[100];
printf("Enter a string\n");
scanf("%s", words);
split(words);
 }
char*split(字符字[50])
{
int i=0;
char*words\u dup=malloc(strlen(words)+1);
strcpy(单词重复,单词);
而(单词!='\0')
{
char*word=strtok(单词,”;
勾选单词(*单词);
char*year=strtok(NULL,“#5944
i=atoi(年);
检查年份(i);
char*definition=strtok(NULL,“###"”);
检查定义(*定义);
char*synonyms=strtok(NULL,##));
勾选同义词(*同义词);
printf(“%s\t”,word);
printf(“%i\t”,i);
printf(“%s\t”,定义);
printf(“%s\t”,同义词);
}
//现在恢复文字
strcpy(单词,单词重复);
免费(大写);
返回0;
}
//------------------------------------------------------------------//
//检查是否合法
//------------------------------------------------------------------//
无效校验字(字符字)
{

如果(word>='A'&&word,则不应使用
atoi
,而应使用非空的结束指针(或…):

然后对
end
执行一些合理的操作,可能将其传递给
strtok
,也可能传递给或查找相关的下一个字符

我相信你的用法是错误的。也许考虑一下<代码> %n>代码>。参见类似的问题。

我不明白你的总体意见,但也许你只是想:

bool parse_line(const char*line, int* pyear)
{
   int pos= -1;
   int year=0;
   if (sscanf(line, "%*[a-z]_#_%d_#_%*[a-z] %n", &year, &pos)>0 && pos>0
              && pos == strlen(line)) {
      *pyear = year;
      return true;
   } else return false;
}
您稍后将使用(在阅读整个
行之后
with或else)调用的

不要忘记使用所有警告和调试信息进行编译(例如,
gcc-Wall-g
),并使用调试器(例如,
gdb
),特别是要一步一步地运行您的错误程序!

示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *str_dup(const char *str){//use strdup if exist strdup
    char *sdup = malloc(strlen(str)+1);
    if(sdup)
        return strcpy(sdup, str);
    return NULL;
}
char *strtokByWord_r(char *str, const char *word, char **store){
    char *p, *ret;
    if(str != NULL){
        *store = str;
    }
    if(*store == NULL) return NULL;
    p = strstr(ret=*store, word);
    if(p){
        *p='\0';
        *store = p + strlen(word);
    } else {
        *store = NULL;
    }
    return ret;
}
char *strtokByWord(char *str, const char *word){
    static char *store = NULL;
    return strtokByWord_r(str, word, &store);
}

typedef struct record {
    char *word;
    int year;
    char *definition;
    char *synonyms;
} Record;

Record *get_rec(const char *input_string){
    Record *rec;
    char* words_dup = str_dup(input_string);
    rec = malloc(sizeof(Record));

    char *word=strtokByWord(words_dup, "_#_");
    //if(check_word(word)!=Valid)
    //{ fprintf(stderr, "bad format\n"); free(rec);/*free(words_dup);...*/ return NULL;}
    rec->word = str_dup(word);

    char *year=strtokByWord(NULL, "_#_");
    rec->year =atoi(year);

    char *definition=strtokByWord(NULL,"_#_");
    rec->definition = str_dup(definition);

    char *synonyms=strtokByWord(NULL,"_#_");
    char *newline = strchr(synonyms, '\n');
    if(newline)
        *newline = '\0';
    rec->synonyms = str_dup(synonyms);

    free(words_dup);

    return rec;
}

int main(void){
    const char *input = "hello_#_2003_#_now_#_MY\n";
    Record *r = get_rec(input);
    printf("%s\t", r->word);
    printf("%i\t",r->year);
    printf("%s\t", r->definition);
    printf("%s\n", r->synonyms);
    free(r->word);free(r->definition);free(r->synonyms);
    free(r);
    return 0;
}
#包括
#包括
#包括
char*str_dup(const char*str){//如果存在strdup,则使用strdup
char*sdup=malloc(strlen(str)+1);
如果(sdup)
返回strcpy(sdup,str);
返回NULL;
}
char*strtokByWord\u r(char*str,const char*word,char**store){
字符*p,*ret;
如果(str!=NULL){
*store=str;
}
if(*store==NULL)返回NULL;
p=strstr(ret=*存储,字);
如果(p){
*p='\0';
*store=p+strlen(字);
}否则{
*store=NULL;
}
返回ret;
}
char*strtokByWord(char*str,const char*word){
静态字符*存储=NULL;
返回strtokByWord\u r(str、word和store);
}
类型定义结构记录{
字符*字;
国际年;
字符*定义;
char*同义词;
}记录;
记录*获取记录(常量字符*输入字符串){
记录*rec;
char*words\u dup=str\u dup(输入字符串);
rec=malloc(sizeof(记录));
char*word=strtokByWord(单词dup,”);
//如果(检查单词(word)!=有效)
//{fprintf(stderr,“坏格式”\n”);free(rec);/*free(words_dup);…*/returnnull;}
rec->word=str\u dup(word);
char*year=strtokByWord(空,“##"”);
rec->year=atoi(年);
char*definition=strtokByWord(NULL,“##"”);
记录->定义=str_dup(定义);
char*synonyms=strtokByWord(NULL,“##"”);
char*newline=strchr(同义词“\n”);
如果(换行)
*换行符='\0';
rec->synonyms=str_dup(同义词);
免费(大写);
返回记录;
}
内部主(空){
const char*input=“hello_35;u2003_35;u35; u now_35;u35; u MY\n”;
记录*r=获取记录(输入);
printf(“%s\t”,r->word);
printf(“%i\t”,r->year);
printf(“%s\t”,r->definition);
printf(“%s\n”,r->同义词);
自由(r->单词);自由(r->定义);自由(r->同义词);
自由(r);
返回0;
}

#包括
#包括
#包括
bool是低的(常量字符*str){
对于(;*str;++str)
如果(!islower(*str))
返回false;
return true;//若调用为_lowers(“”),则返回值应为true还是false?
}
内部主(空){
字符单词[]=“单词”;
如果(是(字))
printf(“有效\n”);
其他的
printf(“无效\n”);
字[0]=“W”;
如果(是(字))
printf(“有效\n”);
其他的
printf(“无效\n”);
返回0;
}

您不应该使用
atoi
,因为它不允许您知道它是否能够解析其输入,但仍然返回一个int。但是为了练习的目的,让我们假设它是可以的,因为输入是好的(即有符号整数)

然后,关于代码的一些注释:

split
不需要返回
char*
,事实上,您将其称为void,因此将split更改为
void split…
;在任何情况下,保持
char*split…
,它应该返回
NULL
,而不是
0

这些线

char* words_dup = malloc(strlen(words)+1);
strcpy(words_dup,words);
可以简单

char *words_dup = strdup(words);
那么

words
是一个指针(
char*
),不是字符,所以它应该是
*words
,或者您的意思是
words!=NULL
,但是
words
不会更改为循环,所以您将永远循环

我想你的意思是在一个连续的流中解析包含单词、年份、定义、同义词的“块”的“流”

如果是这样的话,你必须只使用一次
word=strtok(words,“##)
,然后使用
word=strtok(NULL,“##)

 char *word;

 // use words_dup to avoid changing words.
 for (word = strtok(words_dup, sep); word != NULL; word = strtok(NULL, sep))
 {
        check_word(word);
        // ...
 }
(通常,每次尝试获取新信息时,都应该检查strtok是否返回NULL;如果需要,可以使用
break
退出for循环)

如果不是这样,则根本不需要循环:如果有多行输入,则为每行输入调用“split”

使用
“#”
可以按照您的意愿工作,而不是出于您可能认为的原因(该参数是一组字符,每个字符单独被视为分隔符),而是
char* words_dup = malloc(strlen(words)+1);
strcpy(words_dup,words);
char *words_dup = strdup(words);
while (words!='\0')
 char *word;

 // use words_dup to avoid changing words.
 for (word = strtok(words_dup, sep); word != NULL; word = strtok(NULL, sep))
 {
        check_word(word);
        // ...
 }
char *year=strtok(NULL, "_#_");;  // assigning NULL…
i=atoi(year);
check_year(i);
free(words_dup);
int is_lowecase(const char *str)
{
    while (*str != '\0') {
       if (*str < 'a' || *str > 'z') return 0;
       str++;
    }
    return 1; // anything != 0 is "read" as true
}
 int check_word(const char *word)
 {
   // only all lowercase words are legal
   if (!is_lowercase(word)) {
      // fprintf(stderr, "...");
      // indeed I think it should be a caller duty to print
      // such messages
      printf("word: not legal\n");
      return 0;
   }
   return 1;
 }
 if (!check_A_Test(datum)) {
     // false (0) is Wrong, true (!= 0) is Right, thus the !
     // message here, if you want
     break; // stop parsing
 }