加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 为什么全局变量在不同方法中表现不同?

发布时间:2020-12-16 09:58:24 所属栏目:百科 来源:网络整理
导读:目标: 创建字符串(字典)的全局数组,只要在函数load()中可以计算大小. 使用功能打印()在屏幕上打印字典. 我的方法: 创建指向string的全局指针,在load()中创建字符串数组,并将本地数组分配给全局指针. 问题: 如果我尝试在load()中打印全局数组(以及本地数据
目标:

>创建字符串(字典)的全局数组,只要在函数load()中可以计算大小.
>使用功能打印()在屏幕上打印字典.

我的方法:

创建指向string的全局指针,在load()中创建字符串数组,并将本地数组分配给全局指针.

问题:

如果我尝试在load()中打印全局数组(以及本地数据),一切都很好,但是如果使用print()进行打印,则会在数组末尾的某处发生段错误. GDB和valgrind输出对我来说似乎很神秘.我放弃.怎么了?

来源和字典是here.

码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// length of the longest word in dictionary
#define LENGTH 45
// dictionary file
#define DICTIONARY "large"

// prototypes
void load(const char* dictionary);
void print(void);

// global dictionary size
int dict_size = 0;
// global dictionary
char **global_dict;

int main(void)
{
    load(DICTIONARY);
    print();
    return 0;  
}

/**
 * Loads dictionary into memory.
 */
void load(const char* dictionary)
{
    // open dictionary file
    FILE *dict_file = fopen(dictionary,"r");    

    // compute size of dictionary
    for (int c = fgetc(dict_file); c != EOF; c = fgetc(dict_file))
    {
        // look for 'n' (one 'n' means one word)
        if (c == 'n')
        {
            dict_size++;
        }
    }

    // return to beginning of file
    fseek(dict_file,SEEK_SET);

    // local array
    char *dict[dict_size];

    // variables for reading
    int word_length = 0;
    int dict_index = 0;
    char word[LENGTH + 1];   

    // iteration over characters
    for (int c = fgetc(dict_file); c != EOF; c = fgetc(dict_file))
    {
        // allow only letters
        if (c != 'n')
        {
            // append character to word
            word[word_length] = c;
            word_length++;
        }
        // if c = n and some letters're already in the word
        else if (word_length > 0)
        {
            // terminate current word
            word[word_length] = '';

            //write word to local dictionary
            dict[dict_index] = malloc(word_length + 1);
            strcpy(dict[dict_index],word);
            dict_index++;

            // prepare for next word
            word_length = 0;
        }
    }

    // make local dictioinary global
    global_dict = dict;
}

/**
 * Prints dictionary.
 */
void print(void)
{
    for (int i = 0; i < dict_size; i++)
        printf("%s %pn",global_dict[i],global_dict[i]);
}

解决方法

答案很简单,你将指针指向load()本地的变量,并在load()返回时释放它,因此它在print()中无效,导致未定义的行为.

你甚至评论过它

// local array <-- this is your comment not mine
char *dict[dict_size];

您有两种选择:

>不要使用全局变量,与全局变量一起使用的模式没有任何好处,相反,它非常危险.您可以从函数load()返回动态分配的poitner,然后将其传递给print().
>使用malloc()分配指针数组.

global_dict = malloc(dict_size * sizeof(*global_dict));

为什么我不喜欢全局变量?

>因为您可以在程序中执行您在程序中所做的操作,甚至不会收到编译器发出的警告.

但是当然,当你获得经验时,你不会做这种事情,所以它更多是你的错,而不是全局变量,但是看到程序员还在学习,使用全局变量来解决共享数据的问题是很常见的.在函数中,这是参数的用途.

所以使用不知道如何正确处理它们的全局变量是不好的,而是学习函数参数,你将解决所有需要全局变量通过程序中的不同函数传递数据而不使用全局变量的问题.

这是你自己的代码,我删除了global_dict变量,并在load()中使用了动态内存分配,我也对malloc()执行了一些错误检查,你应该改进那部分,如果你想要代码是健壮的,其余的是自我解释

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// length of the longest word in dictionary
#define LENGTH 45
// dictionary file
#define DICTIONARY "large"

// prototypes
char **load(const char *dictionary);
void print(char **);

int main(void)
{
    char **dictionary;

    dictionary = load(DICTIONARY);
    if (dictionary == NULL)
        return -1;
    print(dictionary);

    /* Don't forget to free resources,you might need to do it while
       the program is still running,leaked resources might quickly 
       become a problem.
     */
    for (int i = 0 ; dictionary[i] != NULL ; ++i)
        free(dictionary[i]);
    free(dictionary);

    return 0;  
}
/**
 * Loads dictionary into memory.
 */
char **load(const char *dictionary)
{
    // open dictionary file
    FILE  *dict_file;    
    size_t dict_size;
    char **dict;
    char   word[LENGTH + 1];
    size_t word_length;
    size_t dict_index;
    dict_file = fopen(dictionary,"r");
    if (dict_file == NULL) /* you should be able to notify this */
        return NULL; /* failure to open file */
    // compute size of dictionary
    for (int c = fgetc(dict_file); c != EOF; c = fgetc(dict_file))
    {
        // look for 'n' (one 'n' means one word)
        if (c == 'n')
        {
            dict_size++;
        }
    }
    // return to beginning of file
    fseek(dict_file,SEEK_SET);

    // local array
    dict = malloc((1 + dict_size) * sizeof(*dict));
    /*                    ^ add a sentinel to avoid storing the number of words */
    if (dict == NULL)
        return NULL;

    // variables for reading
    word_length = 0;
    dict_index = 0;
    // iteration over characters
    for (int c = fgetc(dict_file); c != EOF; c = fgetc(dict_file))
    {
        // allow only letters
        if (c != 'n')
        {
            // append character to word
            word[word_length] = c;
            word_length++;
        }
        // if c = n and some letters're already in the word
        else if (word_length > 0)
        {
            // terminate current word
            word[word_length] = '';

            //write word to local dictionary
            dict[dict_index] = malloc(word_length + 1);
            if (dict[dict_index] != NULL)
            {
                strcpy(dict[dict_index],word);
                dict_index++;
            }
            // prepare for next word
            word_length = 0;
        }
    }
    dict[dict_index] = NULL;
    /* We put a sentinel here so that we can find the last word ... */
    return dict;
}

/**
 * Prints dictionary.
 */
void print(char **dict)
{
    for (int i = 0 ; dict[i] != NULL ; i++)
        printf("%s %pn",dict[i],(void *) dict[i]);
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读