簡體   English   中英

C - 為什么我的函數返回NULL?

[英]C - Why is my function returning NULL?

我認為我的函數返回NULL因為我將它初始化為它。 但如果我不這樣做,我會得到編譯錯誤。

這只是我在test.c文件中進行測試的原型。 因此,當我開始工作時,我會將lookup功能復制回正確的文件中。

這是pset6cs50一部分,如果這有助於任何人。

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)];

您沒有為尾隨空字符保留空間,並且您從未設置它! 例如, char temp[strlen(extension) + 1] = {0};

然后:

char* filetype = NULL;

if (strcmp(temp,  "html") == 0)
    strcpy(filetype, "text/html"); 

必須分配filetype指向對象,例如使用malloc ,否則strcpy使用空指針進行復制。

您確定該extension僅包含擴展名. 我更喜歡使用_stricmpstrcmpi來比較不區分大小寫。 為什么你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 temp[strlen(extension)];

在C中,字符串以NULL結尾,因此您實際上不會為終止字符保留空間,因此您的臨時字符串實際上可能在運行時看起來更長。

改為:

char temp[strlen(extension)+1];

后來:

temp[i] = '\0';

您必須為終止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]= '\0';

另請注意,如果擴展名包含數字或任何其他非字母字符,則不會復制該字符。

你在臨時房中沒有額外的'\\ 0'額外空間; 你需要寫類似的東西

char temp[strlen(extension) + 1];

並分配一些空間來存儲文件類型; 可能是寫作

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文件中,這可能會阻止重新編譯所有內容,但這是另一個故事)

1.您的代碼表現出未定義的行為。 在你的函數lookup -

char temp[strlen(extension)];     // basically char temp[3]

並使用循環填充完整數組,不留空間'\\0'然后使用%s打印並將其傳遞給strcmp也會導致UB

像這樣聲明你的數組temp -

char temp[strlen(extension)+1)]={'\0'};        // +1 for null character

2.當您復制指針filetype -

if (strcmp(temp,  "html") == 0)
    strcpy(filetype, "text/html"); 

但它指向NULL因為它沒有分配任何內存。

使用malloc將內存分配給filetype

char* filetype = NULL沒有使用strcpy函數復制字符串的內存空間。 將此代碼替換為char* filetype = malloc(20)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM