C - 为什么我的函数返回 NULL?
C - Why is my function returning NULL?
我认为我的函数正在返回 NULL
,因为我将它初始化为它。但是如果我不这样做,我会得到编译错误。
这只是我在 test.c
文件中制作的用于测试的原型。因此,当我让它工作时,我会将 lookup
函数复制回正确的文件中。
如果对任何人有帮助,这是 cs50
的 pset6
的一部分。
const char* lookup(const char* extension);
int main(void)
{
const char* type = "css";
const char* ending = lookup(type);
printf("the exstension: %s\nis of type = %s\n", type, ending);
}
const char* lookup(const char* extension)
{
char temp[strlen(extension)];
for (int i = 0; i < strlen(temp); i++)
{
if (isalpha(extension[i]))
temp[i] = tolower(extension[i]);
}
printf("temp = %s\n", temp);
char* filetype = NULL;
if (strcmp(temp, "html") == 0)
strcpy(filetype, "text/html");
else if(strcmp(temp, "css") == 0)
strcpy(filetype, "text/css");
else if(strcmp(temp, "js") == 0)
strcpy(filetype, "text/js");
else if(strcmp(temp, "jpg") == 0)
strcpy(filetype, "image/jpg");
else if(strcmp(temp, "ico" ) == 0)
strcpy(filetype, "image/x-icon");
else if(strcmp(temp, "gif") == 0)
strcpy(filetype, "image/gif");
else if(strcmp(temp, "png") == 0)
strcpy(filetype, "image/png");
else
return NULL;
return filetype;
}
我正在使用所有正确的库,当我尝试包含它们时它搞砸了我的代码预览!
char temp[strlen(extension)];
您没有为尾随的空字符保留 space 并且您从未设置它!例如,char temp[strlen(extension) + 1] = {0};
.
然后:
char* filetype = NULL;
if (strcmp(temp, "html") == 0)
strcpy(filetype, "text/html");
filetype
指向的对象必须分配,例如使用 malloc
,否则 strcpy
将使用空指针进行复制。
1. 您的代码表现出未定义的行为。在你的函数中 lookup
-
char temp[strlen(extension)]; // basically char temp[3]
并使用循环填充完整数组,不为 '[=14=]'
留下 space 然后使用 %s
打印并将其传递给 strcmp
也会导致 UB.
像这样声明数组 temp
-
char temp[strlen(extension)+1)]={'[=11=]'}; // +1 for null character
2. 同样当你复制指针时 filetype
-
if (strcmp(temp, "html") == 0)
strcpy(filetype, "text/html");
但它指向 NULL
因为它没有分配任何内存。
使用 malloc 为 filetype
分配内存。
小心这个:
char temp[strlen(extension)];
在 C 语言中,字符串以 NULL 终止,因此您实际上不会为终止字符保留 space,因此您的临时字符串在运行时实际上看起来可能更长。
改为这样做:
char temp[strlen(extension)+1];
之后:
temp[i] = '[=12=]';
您必须为终止 null 分配空间并终止字符串:
char temp[strlen(extension)+1];
for (int i = 0; i < strlen(temp); i++)
{
if (isalpha(extension[i]))
temp[i] = tolower(extension[i]);
}
temp[i]= '[=10=]';
另请注意,如果扩展名包含数字或任何其他非字母字符,则不会被复制。
您确定 extension
只包含扩展名而没有 .
吗?我可以更喜欢使用 _stricmp
、strcmpi
来比较不区分大小写。为什么你做 strcpy
到 filetype
而不是赋值?你只有指针没有 malloc
:
const char* lookup(const char* extension)
{
const char* filetype = NULL;
if (_stricmp(extension, "html") == 0)
filetype = "text/html";
else if(_stricmp(extension, "css") == 0)
filetype = "text/css";
else if(_stricmp(extension, "js") == 0)
filetype = "text/js";
else if(_stricmp(extension, "jpg") == 0)
filetype = "image/jpg";
else if(_stricmp(extension, "ico" ) == 0)
filetype = "image/x-icon";
else if(_stricmp(extension, "gif") == 0)
filetype = "image/gif";
else if(_stricmp(extension, "png") == 0)
filetype = "image/png";
return filetype;
}
或更好:
const char* lookup(const char* extension)
{
char * ext[] = { "html", "text/html", "css", "text/css", "js", "text/js", "jpg", "image/jpg", NULL };
for ( int i = 0; ext[i]; i += 2 )
{
if ( !stricmp( extension, ext[i] ) )
return ext[i+1];
}
return NULL;
}
char* filetype = NULL
没有内存 space 无法使用 strcpy
函数复制字符串。将此代码替换为 char* filetype = malloc(20)
。
您在临时文件中缺少尾随的 '\0' 额外空间;你需要写类似
的东西
char temp[strlen(extension) + 1];
并分配一些 space 存储文件类型的位置;可能是写
char filetype[50]; // 50 should be enought for your case
尽管如此,我建议使用 strcasecmp()(函数比较两个字符串,忽略字符的大小写)而不是 strcmp() 并删除似乎无用的文件类型。
它可能是这样的:
#include <stdio.h>
#include <strings.h>
const char *lookup(const char *extension);
int main(void)
{
const char *const type = "css";
const char *ending = lookup(type);
printf("the exstension: %s\nis of type = %s\n", type, ending);
}
const char *lookup(const char *extension)
{
if (strcasecmp(extension, "html") == 0)
return "text/html";
else if (strcasecmp(extension, "css") == 0)
return "text/css";
else if (strcasecmp(extension, "js") == 0)
return "text/js";
else if (strcasecmp(extension, "jpg") == 0)
return "image/jpg";
else if (strcasecmp(extension, "ico" ) == 0)
return "image/x-icon";
else if (strcasecmp(extension, "gif") == 0)
return "image/gif";
else if (strcasecmp(extension, "png") == 0)
return "image/png";
return NULL;
}
更具可扩展性的解决方案可以使用数组来描述扩展,这样您在添加新类型时就无需更改代码:
#include <stdio.h>
#include <strings.h>
struct Type {
const char *const extension;
const char *const mime;
} knownTypes[] = {
{ "html", "text/html" },
{ "css", "text/css" },
{ "js", "text/js" },
{ "jpg", "image/jpg" },
{ "ico", "image/x-icon" },
{ "gif", "image/gif" },
{ "png", "image/png" }
};
static const size_t nbKnownTypes = sizeof(knownTypes) / sizeof(struct Type);
const char* lookup(const char* extension);
int main(void)
{
const char *const type = "Css";
const char *ending = lookup(type);
printf("the exstension: %s\nis of type = %s\n", type, ending);
}
const char *lookup(const char *extension)
{
for (size_t i = 0; i < nbKnownTypes; i++) {
struct Type type = knownTypes[i];
if (strcasecmp(extension, type.extension) == 0)
return type.mime;
}
return "Unknown mime type";
}
使用这种设置,您可以轻松添加新类型的扩展名和 mime 类型(您可以将此结构放在单独的 c 文件中,这样也可以防止重新编译所有内容,但这是一个其他故事)
我认为我的函数正在返回 NULL
,因为我将它初始化为它。但是如果我不这样做,我会得到编译错误。
这只是我在 test.c
文件中制作的用于测试的原型。因此,当我让它工作时,我会将 lookup
函数复制回正确的文件中。
如果对任何人有帮助,这是 cs50
的 pset6
的一部分。
const char* lookup(const char* extension);
int main(void)
{
const char* type = "css";
const char* ending = lookup(type);
printf("the exstension: %s\nis of type = %s\n", type, ending);
}
const char* lookup(const char* extension)
{
char temp[strlen(extension)];
for (int i = 0; i < strlen(temp); i++)
{
if (isalpha(extension[i]))
temp[i] = tolower(extension[i]);
}
printf("temp = %s\n", temp);
char* filetype = NULL;
if (strcmp(temp, "html") == 0)
strcpy(filetype, "text/html");
else if(strcmp(temp, "css") == 0)
strcpy(filetype, "text/css");
else if(strcmp(temp, "js") == 0)
strcpy(filetype, "text/js");
else if(strcmp(temp, "jpg") == 0)
strcpy(filetype, "image/jpg");
else if(strcmp(temp, "ico" ) == 0)
strcpy(filetype, "image/x-icon");
else if(strcmp(temp, "gif") == 0)
strcpy(filetype, "image/gif");
else if(strcmp(temp, "png") == 0)
strcpy(filetype, "image/png");
else
return NULL;
return filetype;
}
我正在使用所有正确的库,当我尝试包含它们时它搞砸了我的代码预览!
char temp[strlen(extension)];
您没有为尾随的空字符保留 space 并且您从未设置它!例如,char temp[strlen(extension) + 1] = {0};
.
然后:
char* filetype = NULL;
if (strcmp(temp, "html") == 0)
strcpy(filetype, "text/html");
filetype
指向的对象必须分配,例如使用 malloc
,否则 strcpy
将使用空指针进行复制。
1. 您的代码表现出未定义的行为。在你的函数中 lookup
-
char temp[strlen(extension)]; // basically char temp[3]
并使用循环填充完整数组,不为 '[=14=]'
留下 space 然后使用 %s
打印并将其传递给 strcmp
也会导致 UB.
像这样声明数组 temp
-
char temp[strlen(extension)+1)]={'[=11=]'}; // +1 for null character
2. 同样当你复制指针时 filetype
-
if (strcmp(temp, "html") == 0)
strcpy(filetype, "text/html");
但它指向 NULL
因为它没有分配任何内存。
使用 malloc 为 filetype
分配内存。
小心这个:
char temp[strlen(extension)];
在 C 语言中,字符串以 NULL 终止,因此您实际上不会为终止字符保留 space,因此您的临时字符串在运行时实际上看起来可能更长。
改为这样做:
char temp[strlen(extension)+1];
之后:
temp[i] = '[=12=]';
您必须为终止 null 分配空间并终止字符串:
char temp[strlen(extension)+1];
for (int i = 0; i < strlen(temp); i++)
{
if (isalpha(extension[i]))
temp[i] = tolower(extension[i]);
}
temp[i]= '[=10=]';
另请注意,如果扩展名包含数字或任何其他非字母字符,则不会被复制。
您确定 extension
只包含扩展名而没有 .
吗?我可以更喜欢使用 _stricmp
、strcmpi
来比较不区分大小写。为什么你做 strcpy
到 filetype
而不是赋值?你只有指针没有 malloc
:
const char* lookup(const char* extension)
{
const char* filetype = NULL;
if (_stricmp(extension, "html") == 0)
filetype = "text/html";
else if(_stricmp(extension, "css") == 0)
filetype = "text/css";
else if(_stricmp(extension, "js") == 0)
filetype = "text/js";
else if(_stricmp(extension, "jpg") == 0)
filetype = "image/jpg";
else if(_stricmp(extension, "ico" ) == 0)
filetype = "image/x-icon";
else if(_stricmp(extension, "gif") == 0)
filetype = "image/gif";
else if(_stricmp(extension, "png") == 0)
filetype = "image/png";
return filetype;
}
或更好:
const char* lookup(const char* extension)
{
char * ext[] = { "html", "text/html", "css", "text/css", "js", "text/js", "jpg", "image/jpg", NULL };
for ( int i = 0; ext[i]; i += 2 )
{
if ( !stricmp( extension, ext[i] ) )
return ext[i+1];
}
return NULL;
}
char* filetype = NULL
没有内存 space 无法使用 strcpy
函数复制字符串。将此代码替换为 char* filetype = malloc(20)
。
您在临时文件中缺少尾随的 '\0' 额外空间;你需要写类似
的东西char temp[strlen(extension) + 1];
并分配一些 space 存储文件类型的位置;可能是写
char filetype[50]; // 50 should be enought for your case
尽管如此,我建议使用 strcasecmp()(函数比较两个字符串,忽略字符的大小写)而不是 strcmp() 并删除似乎无用的文件类型。 它可能是这样的:
#include <stdio.h>
#include <strings.h>
const char *lookup(const char *extension);
int main(void)
{
const char *const type = "css";
const char *ending = lookup(type);
printf("the exstension: %s\nis of type = %s\n", type, ending);
}
const char *lookup(const char *extension)
{
if (strcasecmp(extension, "html") == 0)
return "text/html";
else if (strcasecmp(extension, "css") == 0)
return "text/css";
else if (strcasecmp(extension, "js") == 0)
return "text/js";
else if (strcasecmp(extension, "jpg") == 0)
return "image/jpg";
else if (strcasecmp(extension, "ico" ) == 0)
return "image/x-icon";
else if (strcasecmp(extension, "gif") == 0)
return "image/gif";
else if (strcasecmp(extension, "png") == 0)
return "image/png";
return NULL;
}
更具可扩展性的解决方案可以使用数组来描述扩展,这样您在添加新类型时就无需更改代码:
#include <stdio.h>
#include <strings.h>
struct Type {
const char *const extension;
const char *const mime;
} knownTypes[] = {
{ "html", "text/html" },
{ "css", "text/css" },
{ "js", "text/js" },
{ "jpg", "image/jpg" },
{ "ico", "image/x-icon" },
{ "gif", "image/gif" },
{ "png", "image/png" }
};
static const size_t nbKnownTypes = sizeof(knownTypes) / sizeof(struct Type);
const char* lookup(const char* extension);
int main(void)
{
const char *const type = "Css";
const char *ending = lookup(type);
printf("the exstension: %s\nis of type = %s\n", type, ending);
}
const char *lookup(const char *extension)
{
for (size_t i = 0; i < nbKnownTypes; i++) {
struct Type type = knownTypes[i];
if (strcasecmp(extension, type.extension) == 0)
return type.mime;
}
return "Unknown mime type";
}
使用这种设置,您可以轻松添加新类型的扩展名和 mime 类型(您可以将此结构放在单独的 c 文件中,这样也可以防止重新编译所有内容,但这是一个其他故事)