创建一个C语言中的字符串链表。

huangapple go评论82阅读模式
英文:

creating a linkedlist of strings in C

问题

我想制作一个C语言中的十六进制转二进制转换函数,我的实现计划是将十六进制中的字符转换为一串二进制数字,将该字符数组字符串放入链表中,并打印出该链表。然而,当我运行它时,它出现了段错误,并且我不知道如何使用gdb进行调试,因为它是在汇编中。因此,有人可以指出我错在哪里吗?

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

int main(int argc, char* argv[])
{
    for (int i = 1; i < argc; i++) {
        hexToBinary(argv[i]);
        printf("\n");
    }
    return 0;
}

typedef struct hexString {
    char* data;
    struct hexString* next;
} hexString;

hexString* head = NULL;

void add(char* bits, hexString* ptr) {
    hexString* temp = (hexString*)malloc(sizeof(hexString));
    temp->data = bits;
    temp->next = NULL;
    if (head == NULL) {
        head = temp;
    }
    else {
        ptr = head;
        while (ptr->next != NULL) {
            ptr = ptr->next;
        }
        ptr->next = temp;
    }
    free(temp);
}

void display(hexString* ptr) {
    if (head == NULL) {
        printf("There is nothing here");
    }
    else {
        hexString* ptr;
        while (ptr != NULL) {
            printf("%s", ptr->data);
        }
        ptr = ptr->next;
    }
}

char* H2B_MAP(char hex) {
    switch (hex) {
    case '0':
        return "0000";
    case '1':
        return "0001";
    case '2':
        return "0010";
    case '3':
        return "0011";
    case '4':
        return "0100";
    case '5':
        return "0101";
    case '6':
        return "0110";
    case '7':
        return "0111";
    case '8':
        return "1000";
    case '9':
        return "1001";
    case 'A':
    case 'a':
        return "1010";
    case 'B':
    case 'b':
        return "1011";
    case 'C':
    case 'c':
        return "1100";
    case 'D':
    case 'd':
        return "1101";
    case 'E':
    case 'e':
        return "1110";
    case 'F':
    case 'f':
        return "1111";
    }
}

int hexToBinary(char* hex) {
    hexString x;
    hexString* x_ptr = &x;
    for (int i = 0; i < sizeof(hex); i++) {
        add(H2B_MAP(hex[i]), x_ptr);
    }
    display(x_ptr);
    return 0;
}
英文:

So I wanted to make a hexadecimal to binary converting function in c and my plan of implementation was to change the characters in hex to a string of binary numbers
put that string of characater arrays into a linkedlist
and print out said linked list
however when I run it it segfaults and I don't really know how to debug using gdb considering it is in assembly
hence could someone point me out to where I went wrong?

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &quot;h2b.h&quot;
int main(int argc, char* argv[])
{
for (int i=1; i&lt;argc; i++){
hexToBinary(argv[i]);
printf(&quot;\n&quot;);
}
return 0;
}
typedef struct hexString{
char* data;
struct hexString* next;
}hexString;
hexString* head= NULL;
void add(char* bits, hexString* ptr){
hexString* temp = (hexString*)malloc(sizeof(hexString));
temp-&gt;data = bits;
temp-&gt;next = NULL;
if(head == NULL){
head = temp;
}
else{
ptr = head;
while(ptr-&gt;next != NULL){
ptr = ptr-&gt;next;
}
ptr-&gt;next=temp;
}
free(temp);
}
void display(hexString* ptr){
if (head==NULL){
printf(&quot;There is nothing here&quot;);
}
else{
hexString* ptr;
while(ptr != NULL){
printf(&quot;%s&quot;, ptr-&gt;data);
}
ptr = ptr-&gt;next;
}
}
char* H2B_MAP(char hex){
switch(hex){
case&#39;0&#39;:
return &quot;0000&quot;;
case&#39;1&#39;:
return &quot;0001&quot;;
case &#39;2&#39;:
return &quot;0010&quot;;
case &#39;3&#39;:
return &quot;0011&quot;;
case &#39;4&#39;:
return &quot;0100&quot;;
case &#39;5&#39;:
return &quot;0101&quot;;
case &#39;6&#39;:
return &quot;0110&quot;;
case &#39;7&#39;:
return &quot;0111&quot;;
case &#39;8&#39;:
return &quot;1000&quot;;
case &#39;9&#39;:
return &quot;1001&quot;;
case &#39;A&#39;:
case &#39;a&#39;:
return &quot;1010&quot;;
case &#39;B&#39;:
case &#39;b&#39;:
return &quot;1011&quot;;
case &#39;C&#39;:
case &#39;c&#39;:
return &quot;1100&quot;;
case &#39;D&#39;:
case &#39;d&#39;:
return &quot;1101&quot;;
case &#39;E&#39;:
case &#39;e&#39;:
return &quot;1110&quot;;
case &#39;F&#39;:
case &#39;f&#39;:
return &quot;1111&quot;;
}
}
int hexToBinary(char* hex){ //no need for 0x formatting
hexString x;
hexString* x_ptr =&amp;x;
for(int i=0; i&lt;sizeof(hex); i++){ //internally it is a linked list storing strings so how would you do that, ie convert each number into a different number
add(H2B_MAP(hex[i]), x_ptr);
}
display(x_ptr);
return 0;
}

答案1

得分: 1

你在保持一个指向该内存块的引用后才释放内存!删除对 free() 的调用。

英文:

You're freeing memory after keeping a reference pointing to the block! Remove the call to free().

答案2

得分: 1

你的代码中存在几个问题/错误,但让我们从这里开始:

> 我不太了解如何使用GDB进行调试,因为它是用汇编语言编写的

如果你想成为一名程序员,你必须学会如何使用调试器。所以现在停止编写代码,而是花时间学习如何使用调试器。有几种调试器可供选择。有基于文本的调试器,如GDB,还有基于图形界面的调试器,一旦正确设置,使用起来相当容易。选择一种并学会如何使用它。对于GDB来说,如果你的代码没有正确编译使用了-g选项,那是不正确的。关于如何使用GDB,Stack Overflow上有很多帖子(例如https://stackoverflow.com/q/63647073/4386427)。只需搜索并阅读,直到你掌握了如何使用GDB。

下一步是关于编译器警告。你的代码有许多语句,大多数编译器都会警告。永远不要忽略警告!! 在执行代码之前修复所有警告。

如果你没有收到任何警告,那是因为你使用了太少的编译器选项。如果你使用的是gcc,至少执行以下命令:

gcc -Wall -Wextra -pedantic h2b.c -o h2b

更好的做法是:

gcc -Wall -Wextra -pedantic -Werror h2b.c -o h2b

因为-Werror会将所有警告转化为错误,这样你就被迫修复所有警告。

像这样编译你的代码会得到以下错误:

h2b.c: 在函数‘display’中:
h2b.c:40:25: 错误: 未使用的参数‘ptr’ [-Werror=unused-parameter]
   40 | void display(hexString* ptr){
      |              ~~~~~~~~~~~^~~
h2b.c: 在函数‘hexToBinary’中:
h2b.c:100:19: 错误: 整数表达式间的比较: ‘int’ 和 ‘long unsigned int’ [-Werror=sign-compare]
  100 |     for(int i=0; i<sizeof(hex); i++){ //internally it is a linked list storing strings so how would you do that, ie convert each number into a different number
      |                   ^
h2b.c: 在函数‘H2B_MAP’中:
h2b.c:95:1: 错误: 非void函数最后没有return语句 [-Werror=return-type]
   95 | }
      | ^
h2b.c: 在函数‘display’中:
h2b.c:46:19: 错误: ‘ptr’可能在此处未初始化 [-Werror=maybe-uninitialized]
   46 |         while(ptr != NULL){
      |                   ^
h2b.c:45:20: 注意: ‘ptr’在此处声明
   45 |         hexString* ptr;
      |                    ^~~
在函数‘display’中,
    在‘hexToBinary’中以内联方式(inlined)从‘main’调用,位于h2b.c:9:9:
h2b.c:46:19: 错误: ‘ptr’可能在此处未初始化 [-Werror=maybe-uninitialized]
   46 |         while(ptr != NULL){
      |                   ^
h2b.c: 在函数‘main’中:
h2b.c:45:20: 注意: ‘ptr’在此处声明
   45 |         hexString* ptr;
      |                    ^~~
在函数‘display’中,
    在‘hexToBinary’中以内联方式(inlined)从‘main’调用,位于h2b.c:103:5:
h2b.c:46:19: 错误: ‘ptr’未初始化 [-Werror=uninitialized]
   46 |         while(ptr != NULL){
      |                   ^
h2b.c: 在函数‘hexToBinary’中:
h2b.c:45:20: 注意: ‘ptr’在此处声明
   45 |         hexString* ptr;
      |                    ^~~
cc1: 所有警告都被视为错误

接下来,修复所有这些警告/错误。然后,你会发现大部分代码中的错误。

还有一些错误,仅通过修复警告无法找到。所以这里有一些额外的提示:

free(temp); 是错误的。在不再使用内存之前不要释放它。

sizeof(hex) 不会产生你期望的结果。也许考虑使用strlen

代码:

while(ptr != NULL){
    printf("%s", ptr->data);
}

是一个无限循环。在while中改变ptr以避免无限循环。

英文:

There are several problems/bugs in your code but let's start here:

> I don't really know how to debug using gdb considering it is in assembly

If you want to be a programmer you must learn how to use a debugger. So stop writing code for now. Instead spend your time learning how to use a debugger. There are several debuggers avaible. Text based debuggers like gdb but also gui based debuggers that are quite easy to use once they are setup correctly. Choose one and learn how to use it. For gdb it's not correct that you only have assembly. Most likely you didn't compile your code with -g. There are several post on stackoverflow about using gdb (e.g. https://stackoverflow.com/q/63647073/4386427). Just search and read until you master using gdb.

The next step is about compiler warnings. Your code have many statements that most compilers will warn about. Never ignore warnings !! Fix all warnings before executing the code.

If you didn't get any warnings, it's because you are compiling with too few compiler options. If you are using gcc at least do:

gcc -Wall -Wextra -pedantic h2b.c -o h2b

Even better do:

gcc -Wall -Wextra -pedantic -Werror h2b.c -o h2b

as -Werror turns all warnings into errors so that you are forced to fix all warnings.

Compiling your code like that gives me:

h2b.c: In function &#39;display&#39;:
h2b.c:40:25: error: unused parameter &#39;ptr&#39; [-Werror=unused-parameter]
40 | void display(hexString* ptr){
|              ~~~~~~~~~~~^~~
h2b.c: In function &#39;hexToBinary&#39;:
h2b.c:100:19: error: comparison of integer expressions of different signedness: &#39;int&#39; and &#39;long unsigned int&#39; [-Werror=sign-compare]
100 |     for(int i=0; i&lt;sizeof(hex); i++){ //internally it is a linked list storing strings so how would you do that, ie convert each number into a different number
|                   ^
h2b.c: In function &#39;H2B_MAP&#39;:
h2b.c:95:1: error: control reaches end of non-void function [-Werror=return-type]
95 | }
| ^
h2b.c: In function &#39;display&#39;:
h2b.c:46:19: error: &#39;ptr&#39; may be used uninitialized [-Werror=maybe-uninitialized]
46 |         while(ptr != NULL){
|                   ^
h2b.c:45:20: note: &#39;ptr&#39; was declared here
45 |         hexString* ptr;
|                    ^~~
In function &#39;display&#39;,
inlined from &#39;hexToBinary&#39; at h2b.c:103:5,
inlined from &#39;main&#39; at h2b.c:9:9:
h2b.c:46:19: error: &#39;ptr&#39; may be used uninitialized [-Werror=maybe-uninitialized]
46 |         while(ptr != NULL){
|                   ^
h2b.c: In function &#39;main&#39;:
h2b.c:45:20: note: &#39;ptr&#39; was declared here
45 |         hexString* ptr;
|                    ^~~
In function &#39;display&#39;,
inlined from &#39;hexToBinary&#39; at h2b.c:103:5:
h2b.c:46:19: error: &#39;ptr&#39; is used uninitialized [-Werror=uninitialized]
46 |         while(ptr != NULL){
|                   ^
h2b.c: In function &#39;hexToBinary&#39;:
h2b.c:45:20: note: &#39;ptr&#39; was declared here
45 |         hexString* ptr;
|                    ^~~
cc1: all warnings being treated as errors

Go ahead and fix all these warnings/errors. Then you'll find most of the bugs in your code.

There are some bugs you won't find just by fixing warnings. So here are some extra tips:

free(temp); is wrong. Don't free the memory until you are done using it.

sizeof(hex) is not doing what you expect. Maybe consider strlen instead.

The code

    while(ptr != NULL){
printf(&quot;%s&quot;, ptr-&gt;data);
}

is an endless loop. ptr must be changed inside the while to avoid an endless loop.

huangapple
  • 本文由 发表于 2023年8月9日 12:46:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76864650-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定