C 在没有内置函数的情况下拆分数组
下面的代码旨在获取输入字符串,如我的名字是Smith和outputsC 在没有内置函数的情况下拆分数组,c,loops,tokenize,c-strings,C,Loops,Tokenize,C Strings,下面的代码旨在获取输入字符串,如我的名字是Smith和outputs My name is Smith 而且还必须排除以下内容:。空间,只有这三个,但它输出,我不允许使用任何像strlen或strtok这样的东西 我在代码中的任何地方都搜索到了错误,但我似乎无法找到它 int main() { int wordSize = 0; char str[81]; char* ptr_to_word[81]; gets_s(str); for (cha
My
name
is
Smith
而且还必须排除以下内容:。空间,只有这三个,但它输出,我不允许使用任何像strlen或strtok这样的东西
我在代码中的任何地方都搜索到了错误,但我似乎无法找到它
int main()
{
int wordSize = 0;
char str[81];
char* ptr_to_word[81];
gets_s(str);
for (char* res_p = &(str[0]); *res_p != '\0'; res_p++) {
if ((*res_p != '.') || (*res_p != ',') || (*res_p != ' '))
{
ptr_to_word[wordSize] = res_p;
wordSize++;
}
}
if (wordSize == 0)
{
printf("no solution");
}
else
{
for (int i = 0; i < wordSize; i)
{
char* a = ptr_to_word[i];
while ((*a != '.') && (*a != ',') && (*a != ' ') && (*a != '\0'))
{
printf("%c", *a);
a++;
}
printf("\n");
}
}
return 0;
}
在该循环中if语句的条件下
for (char* res_p = &(str[0]); *res_p != '\0'; res_p++) {
if ((*res_p != '.') || (*res_p != ',') || (*res_p != ' '))
{
ptr_to_word[wordSize] = res_p;
wordSize++;
}
}
您必须使用逻辑AND运算符,而不是类似逻辑OR运算符的运算符
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' '))
尽管如此,循环在任何情况下都是错误的,因为变量wordSize不统计单词,而是统计不等于if语句中列出的字符的每个字符
要输出单独的单词,不需要声明指向单词开头的指针数组。一旦找到每个单词的开头,就可以输出它
这是一个非常简单的演示程序
#include <stdio.h>
int main(void)
{
enum { N = 81 };
char s[N];
fgets( s, N, stdin );
for ( const char *p = s; *p; )
{
int wordSize = 0;
while ( *p && *p != '.' && *p != ',' && *p != ' ' && *p != '\t' && *p != '\n' )
{
++wordSize;
++p;
}
if ( wordSize )
{
printf( "%.*s\n", wordSize, p - wordSize );
}
else
{
++p;
}
}
return 0;
}
我在分隔符列表中附加了制表符“\t”和新行符“\n”,可以通过函数fgets插入到输入字符串中。在此循环中的if语句条件下
for (char* res_p = &(str[0]); *res_p != '\0'; res_p++) {
if ((*res_p != '.') || (*res_p != ',') || (*res_p != ' '))
{
ptr_to_word[wordSize] = res_p;
wordSize++;
}
}
您必须使用逻辑AND运算符,而不是类似逻辑OR运算符的运算符
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' '))
尽管如此,循环在任何情况下都是错误的,因为变量wordSize不统计单词,而是统计不等于if语句中列出的字符的每个字符
要输出单独的单词,不需要声明指向单词开头的指针数组。一旦找到每个单词的开头,就可以输出它
这是一个非常简单的演示程序
#include <stdio.h>
int main(void)
{
enum { N = 81 };
char s[N];
fgets( s, N, stdin );
for ( const char *p = s; *p; )
{
int wordSize = 0;
while ( *p && *p != '.' && *p != ',' && *p != ' ' && *p != '\t' && *p != '\n' )
{
++wordSize;
++p;
}
if ( wordSize )
{
printf( "%.*s\n", wordSize, p - wordSize );
}
else
{
++p;
}
}
return 0;
}
我在分隔符列表中添加了制表符“\t”和新行符“\n”,可以通过函数fgets插入到输入字符串中。首先,此条件 如果*res_p!='。|124;*res_p!=','|*回复 永远都是真的,想想看,*res_p永远不是'。'或者不是','。但是,如果将运算符更改为&&您的代码仍将生成相同的结果 带有| |运算符的第一个循环将指向输入字符串中每个字符的指针写入数组ptr|u to|u字,并且仅由于第二个循环中的某个条件,才会打印“s”和“.” 如果将运算符更改为&&如是
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' ')
您将把除“.”、“”和“”之外的所有指针写入数组,例如ptr_to_单词[0]将指向“My name is Smith”,ptr_to_单词[1]指向“y name is Smith”,等等
我已经对您的代码做了一些更改,以便它能够按预期工作
void split_str(char *str)
{
int wordSize = 0;
char *ptr_to_word[81];
char *res_p = &(str[0]);
int i = 0;
for (; *res_p != '\0'; res_p++) {
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' '))
{
wordSize++;
}
else
{
ptr_to_word[i] = res_p - wordSize;
wordSize = 0;
i++;
}
}
ptr_to_word[i] = res_p - wordSize;
ptr_to_word[i + 1] = NULL;
if (i == 0)
{
printf("no solution\n");
}
else
{
for (int i = 0; ptr_to_word[i]; i++)
{
char* a = ptr_to_word[i];
while ((*a != '.') && (*a != ',') && (*a != ' ') && (*a != '\0'))
{
printf("%c", *a);
a++;
}
printf("\n");
}
}
}
int main() {
split_str("My name is Smith\n");
}
这样,只有在遇到点、逗号或空格时,才能将新值写入指针数组。对于所有其他字符,只需执行wordSize++即可跟踪单词的长度。我使用指针算法返回单词ptr_to_word[I]=res_p-wordSize;的开头
我试着对你的代码只做了很小的修改,只做了足够的工作。仍有一些事情需要更改以使其更好,例如,遇到“\0”时第一个循环结束。最后一个单词很可能以“\0”结尾,而不是“.”或“”。因此,它不会写入ptr_to_单词,我必须在循环后手动写入它。此外,您甚至不需要两个循环,您可以使用同一个指针。找到单词后立即输出的算术运算。所以我建议你这样做。自我代码审查,并进一步优化它
祝你好运 首先,这个条件 如果*res_p!='。|124;*res_p!=','|*回复 永远都是真的,想想看,*res_p永远不是'。'或者不是','。但是,如果将运算符更改为&&您的代码仍将生成相同的结果 带有| |运算符的第一个循环将指向输入字符串中每个字符的指针写入数组ptr|u to|u字,并且仅由于第二个循环中的某个条件,才会打印“s”和“.” 如果将运算符更改为&&如是
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' ')
您将把除“.”、“”和“”之外的所有指针写入数组,例如ptr_to_单词[0]将指向“My name is Smith”,ptr_to_单词[1]指向“y name is Smith”,等等
我已经对您的代码做了一些更改,以便它能够按预期工作
void split_str(char *str)
{
int wordSize = 0;
char *ptr_to_word[81];
char *res_p = &(str[0]);
int i = 0;
for (; *res_p != '\0'; res_p++) {
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' '))
{
wordSize++;
}
else
{
ptr_to_word[i] = res_p - wordSize;
wordSize = 0;
i++;
}
}
ptr_to_word[i] = res_p - wordSize;
ptr_to_word[i + 1] = NULL;
if (i == 0)
{
printf("no solution\n");
}
else
{
for (int i = 0; ptr_to_word[i]; i++)
{
char* a = ptr_to_word[i];
while ((*a != '.') && (*a != ',') && (*a != ' ') && (*a != '\0'))
{
printf("%c", *a);
a++;
}
printf("\n");
}
}
}
int main() {
split_str("My name is Smith\n");
}
这样,只有在遇到点、逗号或空格时,才能将新值写入指针数组。对于所有其他字符,只需执行wordSize++即可跟踪单词的长度。我使用指针算法返回单词ptr_to_word[I]=res_p-wordSize;的开头
我试着对你的代码只做了很小的修改,只做了足够的工作。仍有一些事情需要更改以使其更好,例如,遇到“\0”时第一个循环结束。最后一个单词很可能以“\0”结尾,而不是“.”或“”。因此,它不会写入ptr_to_单词,我必须在循环后手动写入它。此外,您甚至不需要两个循环,您可以使用同一个指针。算术
ic在找到单词后立即输出该单词。所以我建议你这样做。自我代码审查,并进一步优化它
祝你好运 您的测试就像一个x | | a!=y | |。。。要明白这些测试永远都是正确的。假设a等于x。那么它不等于y。将| |改为&。你希望a不等于所有的,而不仅仅是一个。@TomKarzes有趣的是,它在底部的while循环中正确地完成了。@Barmar是的,我注意到了。第一个可能是尝试反转测试失败。问题是,您正在为每个非标点符号的字符添加指向ptr_to_单词的指针,而不仅仅是标点符号后的第一个字符。@DanielWalker我会,除了我没有仔细查看它,以确定这是否是唯一的问题。您的测试非常复杂!=x | | a!=y | |。。。要明白这些测试永远都是正确的。假设a等于x。那么它不等于y。将| |改为&。你希望a不等于所有的,而不仅仅是一个。@TomKarzes有趣的是,它在底部的while循环中正确地完成了。@Barmar是的,我注意到了。第一个可能是尝试反转测试失败。问题是,您正在为每个非标点符号的字符添加指向ptr_to_单词的指针,而不仅仅是标点符号后的第一个字符。@DanielWalker我会的,但我没有仔细查看它,以确定这是否是唯一的问题。这很有效,每次在句子的中间有一个定界符,在打印下一个单词之前,它会给一个很大的空间,我试图修复它,但是它只会产生更多的错误。这是有效的,每次在句子中间有一个定界符,在打印下一个单词之前,它会给一个大的空间,我试图修复它,但它只会产生更多的错误。