C 中的 strcmp() 有问题
Having issues with strcmp() in C
我已经为此工作了几个小时,它是为了测试我的理智。
作业是编写一个程序,当它读取一个名称时,它会检查给定结构的名称并查找匹配项,然后显示结构中的其他数据。不管输入字符串的大小写如何,它都应该工作,如果没有匹配名称它应该告诉用户。
当然一切都编译得很好,但是当我输入一个应该命中的名字时(因为它在结构中)它没有看到它。
我知道问题出在调用 strcmp 的某个地方。
如有任何帮助,我们将不胜感激。
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
typedef struct solar
{
char name[50];
char type[50];
double radius;
double mass;
double distsun;
}solar_obj;
void main()
{
char input_name[50];
solar_obj solarobj[] = { { "CERES", "DWARF PLANET", 471, 9.5E20, 413.7E6 },
{ "EARTH", "PLANET", 6380, 5.974E24, 149.6E6 },
{ "ERIS", "DWARF PLANET", 1163, 1.7E22, 10210E6 },
{ "HAUMEA", "DWARF PLANET", 650, 4E21, 6484E6 },
{ "JUPITER", "PLANET", 71500, 1.899E27, 778.4E6 },
{ "MAKEMAKE", "DWARF PLANET", 715, 2.2E21, 6850E6 },
{ "MARS", "PLANET", 3400, 6.419E23, 227.9E6 },
{ "MERCURY", "PLANET", 2440, 3.302E23, 57.9E6 },
{ "NEPTUNE", "PLANET", 24770, 1.024E26, 4498.3E6 },
{ "PLUTO", "DWARF PLANET", 1184, 1.3E22, 5906.4E6},
{ "SATURN", "PLANET", 60270, 5.685E26, 1426.7E6 },
{ "SUN", "STAR", 696000, 1.9891E30, 0 },
{ "URANUS", "PLANET", 25560, 8.685E25, 2870.9E6 },
{ "VENUS", "PLANET", 6050, 4.869E24, 108.2E6 }
};
printf("Please enter the name of the solar object:");
fgets(input_name, sizeof(input_name), stdin);
//to make all inputed string chars into uppercase
for (int i = 0; input_name[i] != '[=10=]'; i++){
input_name[i] = toupper(input_name[i]);
}
//search through struct for matching name then print the data
for (int j = 0; j < 14; j++)
{
if (strcmp(solarobj[j].name, input_name) == 0)
{
printf("\nObject name is : %s \n", solarobj[j].name);
printf("%s is a %s \n", solarobj[j].name, solarobj[j].type);
printf("Radius (km) : %f \n ", solarobj[j].radius);
printf("Mass (kg) : %f\n", solarobj[j].mass);
printf("Distance from sun (km) : %f \n", solarobj[j].distsun);
}
else // if a name that doesnt match anything in the struct tell the user
{
if (j == 13){
printf("No objects in our solar system have the name: %s\n", input_name);
break;
}
continue;
}
}
getch();
}
首先,fgets()
将 newline
保留在条目的末尾。你可以像这样摆脱它。
char *strp = strchr(input_name, '\n'); // look for newline
if (strp) *strp = '[=10=]'; // terminate string
接下来,您可以使用 stricmp()
进行不区分大小写的比较。
if (stricmp(solarobj[j].name, input_name) == 0)
你的循环可以简化成这样
int j;
for (j = 0; j < 14; j++)
{
if (stricmp(solarobj[j].name, input_name) == 0)
{
printf("\nObject name is : %s \n", solarobj[j].name);
printf("%s is a %s \n", solarobj[j].name, solarobj[j].type);
printf("Radius (km) : %f \n ", solarobj[j].radius);
printf("Mass (kg) : %f\n", solarobj[j].mass);
printf("Distance from sun (km) : %f \n", solarobj[j].distsun);
break;
}
}
if (j == 14)
printf("No objects in our solar system have the name: %s\n", input_name);
请注意,我在循环外声明了 j
,因此当我测试是否找到匹配项时,它的作用域仍然有效。
函数 fgets()
的文档说:
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.
变量 input_name
中的值以换行符 ('\n'
) 结尾,当然,它永远不会与列表中的太阳物体名称相匹配。
您可以在开始搜索列表之前将其从字符串中删除(如果存在),从而轻松解决此问题:
void main() {
char input_name[50];
int i;
solar_obj solarobj[] = {
/* the big list here */
};
printf("Please enter the name of the solar object:");
fgets(input_name, sizeof(input_name), stdin);
// make all inputed string chars into uppercase
// stop when reach a new line or the end of the string
for (i = 0; input_name[i] != '\n' && input_name[i] != '[=10=]'; i++) {
input_name[i] = toupper(input_name[i]);
}
// end the string here (replace the newline, if it's there)
input_name[i] = '[=10=]';
//search through struct for matching name then print the data
for (int j = 0; j < 14; j++) {
/* the rest of the original code here */
the following code will perform the desired functionality
contains no no-portable function calls,
checks for input errors
compiles cleanly
#include <stdio.h>
//#include <conio.h> // <-- non portable, do not use
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct solar // < remove clutter from struct definition
{
char name[50];
char type[50];
double radius;
double mass;
double distsun;
};
// use valid main declaration
int main()
{
char input_name[50] = {'[=10=]'}; // initialize input field
// use struct name, not typedef name
// use vertical alignment of braces
// rather than georgian formatting
// for readability
struct solar solarobj[] =
{
{ "CERES", "DWARF PLANET", 471, 9.5E20, 413.7E6 },
{ "EARTH", "PLANET", 6380, 5.974E24, 149.6E6 },
{ "ERIS", "DWARF PLANET", 1163, 1.7E22, 10210E6 },
{ "HAUMEA", "DWARF PLANET", 650, 4E21, 6484E6 },
{ "JUPITER", "PLANET", 71500, 1.899E27, 778.4E6 },
{ "MAKEMAKE", "DWARF PLANET", 715, 2.2E21, 6850E6 },
{ "MARS", "PLANET", 3400, 6.419E23, 227.9E6 },
{ "MERCURY", "PLANET", 2440, 3.302E23, 57.9E6 },
{ "NEPTUNE", "PLANET", 24770, 1.024E26, 4498.3E6 },
{ "PLUTO", "DWARF PLANET", 1184, 1.3E22, 5906.4E6},
{ "SATURN", "PLANET", 60270, 5.685E26, 1426.7E6 },
{ "SUN", "STAR", 696000, 1.9891E30, 0 },
{ "URANUS", "PLANET", 25560, 8.685E25, 2870.9E6 },
{ "VENUS", "PLANET", 6050, 4.869E24, 108.2E6 }
};
// calculate number of entries in table
int tableCount = sizeof(solarobj) / sizeof(struct solar);
printf("Please enter the name of the solar object:");
// always check to assure input operation is successful
if( NULL == fgets(input_name, sizeof(input_name), stdin) )
{ // then fgets failed
perror( "fgets for planet name failed" );
exit( EXIT_FAILURE );
}
// implied else, fgets successful
char *strp = strchr(input_name, '\n'); // look for newline
if (strp) *strp = '[=10=]'; // remove newline, if present
// change all upper case charactgers to lower case
for( int i=0; input_name[i]; i++ ) input_name[i] = tolower(input_name[i]);
int found = 0; // indicate name not found
//search through table for matching name then print the data
for (int j = 0; j < tableCount; j++)
{
if (strcmp(solarobj[j].name, input_name) == 0)
{
printf("\nObject name is : %s \n", solarobj[j].name);
printf("%s is a %s \n", solarobj[j].name, solarobj[j].type);
printf("Radius (km) : %f \n ", solarobj[j].radius);
printf("Mass (kg) : %f\n", solarobj[j].mass);
printf("Distance from sun (km) : %f \n", solarobj[j].distsun);
found = 1; // indicate name found
break;
} // end if
} // end for
if( !found ) printf("No objects in our solar system have the name: %s\n", input_name);
// use common system function, not windows specific function
getchar();
return( 0 );
} // end function: main
我已经为此工作了几个小时,它是为了测试我的理智。
作业是编写一个程序,当它读取一个名称时,它会检查给定结构的名称并查找匹配项,然后显示结构中的其他数据。不管输入字符串的大小写如何,它都应该工作,如果没有匹配名称它应该告诉用户。
当然一切都编译得很好,但是当我输入一个应该命中的名字时(因为它在结构中)它没有看到它。
我知道问题出在调用 strcmp 的某个地方。
如有任何帮助,我们将不胜感激。
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
typedef struct solar
{
char name[50];
char type[50];
double radius;
double mass;
double distsun;
}solar_obj;
void main()
{
char input_name[50];
solar_obj solarobj[] = { { "CERES", "DWARF PLANET", 471, 9.5E20, 413.7E6 },
{ "EARTH", "PLANET", 6380, 5.974E24, 149.6E6 },
{ "ERIS", "DWARF PLANET", 1163, 1.7E22, 10210E6 },
{ "HAUMEA", "DWARF PLANET", 650, 4E21, 6484E6 },
{ "JUPITER", "PLANET", 71500, 1.899E27, 778.4E6 },
{ "MAKEMAKE", "DWARF PLANET", 715, 2.2E21, 6850E6 },
{ "MARS", "PLANET", 3400, 6.419E23, 227.9E6 },
{ "MERCURY", "PLANET", 2440, 3.302E23, 57.9E6 },
{ "NEPTUNE", "PLANET", 24770, 1.024E26, 4498.3E6 },
{ "PLUTO", "DWARF PLANET", 1184, 1.3E22, 5906.4E6},
{ "SATURN", "PLANET", 60270, 5.685E26, 1426.7E6 },
{ "SUN", "STAR", 696000, 1.9891E30, 0 },
{ "URANUS", "PLANET", 25560, 8.685E25, 2870.9E6 },
{ "VENUS", "PLANET", 6050, 4.869E24, 108.2E6 }
};
printf("Please enter the name of the solar object:");
fgets(input_name, sizeof(input_name), stdin);
//to make all inputed string chars into uppercase
for (int i = 0; input_name[i] != '[=10=]'; i++){
input_name[i] = toupper(input_name[i]);
}
//search through struct for matching name then print the data
for (int j = 0; j < 14; j++)
{
if (strcmp(solarobj[j].name, input_name) == 0)
{
printf("\nObject name is : %s \n", solarobj[j].name);
printf("%s is a %s \n", solarobj[j].name, solarobj[j].type);
printf("Radius (km) : %f \n ", solarobj[j].radius);
printf("Mass (kg) : %f\n", solarobj[j].mass);
printf("Distance from sun (km) : %f \n", solarobj[j].distsun);
}
else // if a name that doesnt match anything in the struct tell the user
{
if (j == 13){
printf("No objects in our solar system have the name: %s\n", input_name);
break;
}
continue;
}
}
getch();
}
首先,fgets()
将 newline
保留在条目的末尾。你可以像这样摆脱它。
char *strp = strchr(input_name, '\n'); // look for newline
if (strp) *strp = '[=10=]'; // terminate string
接下来,您可以使用 stricmp()
进行不区分大小写的比较。
if (stricmp(solarobj[j].name, input_name) == 0)
你的循环可以简化成这样
int j;
for (j = 0; j < 14; j++)
{
if (stricmp(solarobj[j].name, input_name) == 0)
{
printf("\nObject name is : %s \n", solarobj[j].name);
printf("%s is a %s \n", solarobj[j].name, solarobj[j].type);
printf("Radius (km) : %f \n ", solarobj[j].radius);
printf("Mass (kg) : %f\n", solarobj[j].mass);
printf("Distance from sun (km) : %f \n", solarobj[j].distsun);
break;
}
}
if (j == 14)
printf("No objects in our solar system have the name: %s\n", input_name);
请注意,我在循环外声明了 j
,因此当我测试是否找到匹配项时,它的作用域仍然有效。
函数 fgets()
的文档说:
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.
变量 input_name
中的值以换行符 ('\n'
) 结尾,当然,它永远不会与列表中的太阳物体名称相匹配。
您可以在开始搜索列表之前将其从字符串中删除(如果存在),从而轻松解决此问题:
void main() {
char input_name[50];
int i;
solar_obj solarobj[] = {
/* the big list here */
};
printf("Please enter the name of the solar object:");
fgets(input_name, sizeof(input_name), stdin);
// make all inputed string chars into uppercase
// stop when reach a new line or the end of the string
for (i = 0; input_name[i] != '\n' && input_name[i] != '[=10=]'; i++) {
input_name[i] = toupper(input_name[i]);
}
// end the string here (replace the newline, if it's there)
input_name[i] = '[=10=]';
//search through struct for matching name then print the data
for (int j = 0; j < 14; j++) {
/* the rest of the original code here */
the following code will perform the desired functionality
contains no no-portable function calls,
checks for input errors
compiles cleanly
#include <stdio.h>
//#include <conio.h> // <-- non portable, do not use
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct solar // < remove clutter from struct definition
{
char name[50];
char type[50];
double radius;
double mass;
double distsun;
};
// use valid main declaration
int main()
{
char input_name[50] = {'[=10=]'}; // initialize input field
// use struct name, not typedef name
// use vertical alignment of braces
// rather than georgian formatting
// for readability
struct solar solarobj[] =
{
{ "CERES", "DWARF PLANET", 471, 9.5E20, 413.7E6 },
{ "EARTH", "PLANET", 6380, 5.974E24, 149.6E6 },
{ "ERIS", "DWARF PLANET", 1163, 1.7E22, 10210E6 },
{ "HAUMEA", "DWARF PLANET", 650, 4E21, 6484E6 },
{ "JUPITER", "PLANET", 71500, 1.899E27, 778.4E6 },
{ "MAKEMAKE", "DWARF PLANET", 715, 2.2E21, 6850E6 },
{ "MARS", "PLANET", 3400, 6.419E23, 227.9E6 },
{ "MERCURY", "PLANET", 2440, 3.302E23, 57.9E6 },
{ "NEPTUNE", "PLANET", 24770, 1.024E26, 4498.3E6 },
{ "PLUTO", "DWARF PLANET", 1184, 1.3E22, 5906.4E6},
{ "SATURN", "PLANET", 60270, 5.685E26, 1426.7E6 },
{ "SUN", "STAR", 696000, 1.9891E30, 0 },
{ "URANUS", "PLANET", 25560, 8.685E25, 2870.9E6 },
{ "VENUS", "PLANET", 6050, 4.869E24, 108.2E6 }
};
// calculate number of entries in table
int tableCount = sizeof(solarobj) / sizeof(struct solar);
printf("Please enter the name of the solar object:");
// always check to assure input operation is successful
if( NULL == fgets(input_name, sizeof(input_name), stdin) )
{ // then fgets failed
perror( "fgets for planet name failed" );
exit( EXIT_FAILURE );
}
// implied else, fgets successful
char *strp = strchr(input_name, '\n'); // look for newline
if (strp) *strp = '[=10=]'; // remove newline, if present
// change all upper case charactgers to lower case
for( int i=0; input_name[i]; i++ ) input_name[i] = tolower(input_name[i]);
int found = 0; // indicate name not found
//search through table for matching name then print the data
for (int j = 0; j < tableCount; j++)
{
if (strcmp(solarobj[j].name, input_name) == 0)
{
printf("\nObject name is : %s \n", solarobj[j].name);
printf("%s is a %s \n", solarobj[j].name, solarobj[j].type);
printf("Radius (km) : %f \n ", solarobj[j].radius);
printf("Mass (kg) : %f\n", solarobj[j].mass);
printf("Distance from sun (km) : %f \n", solarobj[j].distsun);
found = 1; // indicate name found
break;
} // end if
} // end for
if( !found ) printf("No objects in our solar system have the name: %s\n", input_name);
// use common system function, not windows specific function
getchar();
return( 0 );
} // end function: main