【问题标题】:Word count in C, learning more CSC 中的字数,学习更多 CS
【发布时间】:2012-07-13 10:40:36
【问题描述】:

在使用 Python 和 JS 等动态语言进行了大约 5 年的编程之后,我开始觉得自己错过了幕后发生的事情。像这样的语言真的很棒,因为它们让你专注于你必须做的事情,利用指针、内存分配和许多搜索、排序、插入算法的麻烦。尽管我从不后悔使用这些语言,因为我真的觉得它们非常强大,但我觉得,为了成为一名更好的程序员,我需要退后一步,了解幕后发生的事情!

我决定通过编写一个简单的单词计数器来做到这一点:应用程序获取所有参数并输出所有唯一单词,每个单词都有一个计数器:“Hello world Hello”将返回“Hello: 2”、“world: 1"(不考虑实际的输出结构)。该程序相当于 Python:

import sys
from collections import defaultdict

def main():
    results = defaultdict(int)
    for word in sys.argv[1:]:
        results[word] += 1
    print results

用 C 语言编写它有点不同,我觉得我在指针、指针数组和所有这些东西上都搞错了!我想变得更好,帮助我变得更好!

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

// This is what a key-value pair: <int, string>
typedef struct {
    int counter;
    unsigned char* word;
} hashmap;

// Checks if inside the array of results, hashmap->word is equals to word paramter
hashmap* get_word_from_results(hashmap* results[], int count, const char* word) {
    int i;
    hashmap* result;
    for (i = 0; i < count; i++) {
        result = results[i];
        if (result->word == (unsigned char *)word)
            return result;
    }
    return NULL;
}

int main(int argc, const char *argv[])
{
    hashmap* results;
    int results_counter = 0;

    int i;
    const char* word;
    for (i = 1; i < argc; i++) {
        word = argv[i];
        hashmap* result = get_word_from_results(&results, results_counter, word);
        // If result is NULL, means word is not inserted yet, let's create a new hashmap and insert it inside the array
        if (result == NULL) {
            hashmap h;
            h.counter = 1;
            h.word = (unsigned char *)word;

            results = realloc(NULL, (results_counter + 1) * sizeof(hashmap) );
            // NOTE: potential memory leak? would h be deallocated?
            results[results_counter] = h;
            results_counter++;
            printf("NEW\n");
        } else {
            // The word already exists in the hashmap array, let's increase it by 1
            result->counter++;
            printf("INCREMENTED\n");
        }
    }   
    return 0;
}

谁能给我一些建议?我在这里做错了什么?我的指针还好吗?我还想我发现了内存泄漏(参见 cmets),有人愿意提交他们的版本吗??

谢谢!!你们太酷了!!

丹尼尔

【问题讨论】:

  • 1) 您正在比较指针。您应该比较它们指向的字符串。提示:使用 strcmp()。 2) 在插入时,首先将计数器设置为 1,然后将其递增。 3)你也在分配指针。提示:strdup()
  • 我们在这里确实很酷。我们保持冷静的方法之一是严格控制从俱乐部前门进入的东西。我们不会为了一件事而让模糊、广泛或离题的问题出现。您的问题非常模糊,也许更适合codereview.stackexchange.com/?as=1。我们太酷了,我们只回答有关精确编程问题的精确问题。
  • 您可能已经意识到,但只是指出来——您将此数据结构称为 hashmap,然后对其进行线性搜索,这实际上并不是哈希表应该如何工作的。
  • @PirosB3:我会忽略 Ulterior 的评论,这绝对是一个有价值的练习!坚持下去。
  • 碰巧我很少对问题投反对票,也没有对此投反对票。但是,如果您来到 SO,您必须遵守我们的规则,您的问题是题外话(因此票数接近)。如果您不喜欢被否决,请写出更好的问题。哦,让皮肤更厚!

标签: c algorithm pointers malloc information-retrieval


【解决方案1】:

您程序中的主要指针问题是当hashmap* results 第一次传递给realloc 时,它的值未初始化。这是未定义的行为。你应该初始化指向NULL的指针,像这样:

hashmap* results = NULL;

另一个问题是比较字符串:您需要使用strcmp 而不是==。请记住,当字符串相等时,strcmp 返回零。

在您的程序结束时也存在内存泄漏。您应该释放results,以及存储在其元素中的单词。

当然,您称为hashmap 的东西的行为与动态数组完全一样。然而,用 C 语言编写哈希表会带来不同程度的挑战,因此我鼓励您采用当前的方法。

【讨论】:

  • 谢谢!另外,我认为hashmap的实际结构有问题!无符号字符*字;
  • @PirosB3 char* 是正确的类型:C 中的字符串是chars 的以零结尾的序列,所以第一个字符在指针处,第二个字符在指针处加一,第三个是指针加二,以此类推,直到你碰到一个零字节,这意味着已经到达字符串的末尾。
  • 太棒了!这仅适用于 char 或其他所有内容吗?我怎么做指针+1?
  • 这适用于其他一切。你像这样做指针加一:ptr+1。这个和&amp;ptr[1]一样,因为指针可以重新解释为数组,数组也可以重新解释为指针。
  • 好吧:假设我有一个指向整数数组的指针,这对吗?:int*整数;一旦将它分配给我想循环遍历数组的整数数组,将实际数字加 1 和指针加 1 有什么区别? integer++ 会做什么?
猜你喜欢
  • 2021-03-05
  • 2017-03-12
  • 2016-05-09
  • 2013-06-23
  • 1970-01-01
  • 2018-05-28
  • 1970-01-01
  • 2010-09-15
  • 2021-08-09
相关资源
最近更新 更多