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