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

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

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){ //no need for 0x formatting
	hexString x;
	hexString* x_ptr =&x;
	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
		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的问题,stackoverflow上有几篇文章(例如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: In function 'display':
h2b.c:40:25: error: unused parameter 'ptr' [-Werror=unused-parameter]
40 | void display(hexString* ptr){
|              ~~~~~~~~~~~^~~
h2b.c: In function 'hexToBinary':
h2b.c:100:19: error: comparison of integer expressions of different signedness: 'int' and '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: In function 'H2B_MAP':
h2b.c:95:1: error: control reaches end of non-void function [-Werror=return-type]
95 | }
| ^
h2b.c: In function 'display':
h2b.c:46:19: error: 'ptr' may be used uninitialized [-Werror=maybe-uninitialized]
46 |         while(ptr != NULL){
|                   ^

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

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

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.html
匿名

发表评论

匿名网友

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

确定