- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
StackOverflow 上的第一篇文章(贸易测试员,业余时间非常糟糕的程序员)。出于披露目的,这是我正在努力完成的一项大学作业(据我所知,在这里提问并不被禁止。
无论如何,我有一个程序可以从文本文件中读取一行,标记行数据,创建一个链接列表,然后将每个标记(2 个字符串、1 个 float 、1 个无符号)插入到节点中。在节点使用的内存被释放之前一切都很好——整个程序崩溃了。调试后,我似乎将问题隔离到两个字符串复制操作。它们看起来都非常有效,但 free() 根本不喜欢它们。试过 strncpy() - 没有区别。尝试逐个复制字符串 char - 没有区别。现在我不知所措......
下面的代码,如果有人想看一看(哦,更多的披露 - 几乎是一个完整的 C n00b,所以是的,如果你看到下面的不良做法,那就是我......)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "ts.h"
int main(void)
{
/* Variables */
FILE *stream;
char buf[BUFSIZ];
/* Open stock file */ //TODO - make this dynamic, don't hard-code file name
stream = fopen("stock.csv", "r");
assert(stream);
/* Using addStockNode */
while (fgets(buf, BUFSIZ, stream))
{
addStockNode(buf);
}
}
void addStockNode(char* stockLine)
{
//Create linked list
StockNodePtr head, new, current, previous, nextStock;
unsigned listSize;
char *stkTok1, *stkTok2, *stkTok3, *stkTok4;
unsigned stkLevel;
int i;
float stkPrice;
listSize = 0;
head = NULL;
/* Create new stock node */
if ((new = malloc(sizeof(StockNodePtr))) == NULL)
{
fprintf(stderr,"\nMemory allocation for node insertion failed\n");
fprintf(stderr,"Aborting\n");
exit(EXIT_FAILURE);
}
/* Tokenise data */
stkTok1 = strtok(stockLine, ",");
stkTok2 = strtok(NULL, ",");
stkTok3 = strtok(NULL, ",");
stkTok4 = strtok(NULL, ",");
/* Search to find where in insert new list node */ //TODO - needs to be adapted to sort by stock DESCRIPTION
current = head;
previous = NULL;
/* stockID */
// strcpy(new->stockID, stkTok1); //falls over at free()
// strncpy(new->stockID, stkTok1, STOCKID_LEN); //falls over at free()
for(i = 0; i < strlen(stkTok1); i++) //still falls over at free()
{
new->stockID[i] = stkTok1[i];
}
/* description */
// strcpy(new->description, stkTok2); //falls over at free()
/* unitPrice */
stkPrice = strtof(stkTok3, NULL);
new->unitPrice = stkPrice;
/* StockLevel */
stkLevel = strtol(stkTok4, NULL, 10);
new->stockLevel = stkLevel;
/*nextStock */
new->nextStock = current;
/* Increment listSize */
listSize++;
//TAKE OUT LATER - loadData can iterate through each line of the file */
if(previous == NULL)
{
head = new;
}
else
{
previous->nextStock = new;
}
/* Print node details */
current = head;
printf("%s,%s,%f,%i\n", current->stockID, current->description, current->unitPrice, current->stockLevel);
/* Deallocate memory used by node */
current = head;
while(current != NULL)
{
nextStock = current->nextStock;
free(current); //EXECUTE THIS, IT FALLS OVER (with strcpy lines uncommented)
current = nextStock;
}
return EXIT_SUCCESS;
}*
为了完整起见,这里是库存节点结构...
typedef struct stockNode
{
char stockID[STOCKID_LEN + 1];
char description[DESCRIPTION_MAX + 1];
float unitPrice;
unsigned stockLevel;
StockNodePtr nextStock;
} StockNodeType;
如果有人能指出我哪里出错了,我将不胜感激!
编辑 - 这是库存节点常量...
#define STOCKID_LEN 5
#define DESCRIPTION_MAX 40
#define PRICE_COLWIDTH 7
#define STOCKLEVEL_COLWIDTH 3
#define STOCKLEVEL_MAX 100
哦,还有正在添加的股票数据(并不是说它有什么问题)...
S0001,Slazenger Classic Racquet,150.00,5
S0002,Slazenger Lite Racquet,98.00,3
S0003,Wilson Tournament Gold Balls,14.95,20
S0004,Dunlop Grand Prix Balls,10.95,25
S0005,Luft Nemesis Racquet,125.00,1
S0006,Wilson Tournament Balls,12.95,12
最佳答案
if ((new = malloc(sizeof(StockNodePtr))) == NULL)
这意味着您正在分配足够大的空间来容纳指针;不是存量节点。
试试这个:
if ((new = malloc(sizeof(*new))) == NULL)
注意:我没有彻底阅读其余部分,但这本身就相当庞大,因为您永远不会为每个节点分配超过指针大小的内存。如果还有其他问题,我会在看到它们时发表评论。
代码主体内的以下一般性意见和建议不一定与主要缺陷相关。然而,他们中的大多数指出了可能导致 future 缺陷的问题。
变量初始化
关于一般编码实践。 从不声明未初始化的指针。理想情况下,永远不要声明未初始化的任何东西。像这样的事情:
StockNodePtr head, new, current, previous, nextStock;
unsigned listSize;
可以回来真正咬你的屁股。这些应该是这样的:
StockNodePtr head=NULL, new=NULL, currentNULL, previousNULL, nextStockNULL;
unsigned listSize = 0;
如果您担心初始化一个值只是为了在声明后立即将其重写,请不要担心。编译器会为你优化它(volatile not withstanding)。
链表构建
构造尾追加链表的一个常见问题是知道最后一个“下一个”指针在哪里。人们经常混淆两个或三个指针,特殊情况是初始构造时的头指针等。我在这里告诉你这些都不需要。
考虑一下 dbl-pointer(一个保存另一个指针变量地址的指针)如何非常有效地帮助构造期间的尾部追加列表:
StockNodePtr head = NULL;
StockNodePtr *next = &head; // points to the next pointer to assign.
while(not finished)
{
StockNodePtr newNode = malloc(sizeof(*newNode));
// ...
// set all your fields.
//
// whatever pointer `next` points to gets the new node. on an
// initial list it will be the `head` pointer. on a subsequent
// node it will be the `nextStock` pointer of the last-node-added.
*next = newNode;
// now just set the new next-pointer-to-populate to be the `nextStock`
// pointer of the node we just added.
next = &newNode->nextStock;
}
// terminate the last node
*next = NULL;
前面代码中的next
指针始终保存着下一个要填充的指针的地址。最初它填充有 head
指针变量的地址。当循环结束时,next
指向的任何指针都需要设置为 NULL 以终止列表。注意:设置字段时不需要设置 newNode->nextStock = NULL;
。循环的下一次迭代将为您设置它(到下一个节点)或 *next = NULL;
如果它是最后添加的节点,则循环后将其设置为 NULL。
我会深入研究 strtok()
的用法和所有这些指针,但我晚饭晚了,我的另一半正在打电话。我希望这至少有所帮助。祝你好运,祝你有个炸药日。
关于C——在释放内存时将字符串数据插入链表会使程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16258202/
如何使用 SPListCollection.Add(String, String, String, String, Int32, String, SPListTemplate.QuickLaunchO
我刚刚开始使用 C++ 并且对 C# 有一些经验,所以我有一些一般的编程经验。然而,似乎我马上就被击落了。我试过在谷歌上寻找,以免浪费任何人的时间,但没有结果。 int main(int argc,
这个问题已经有答案了: In Java 8 how do I transform a Map to another Map using a lambda? (8 个回答) Convert a Map>
我正在使用 node + typescript 和集成的 swagger 进行 API 调用。我 Swagger 提出以下要求 http://localhost:3033/employees/sear
我是 C++ 容器模板的新手。我收集了一些记录。每条记录都有一个唯一的名称,以及一个字段/值对列表。将按名称访问记录。字段/值对的顺序很重要。因此我设计如下: typedef string
我需要这两种方法,但j2me没有,我找到了一个replaceall();但这是 replaceall(string,string,string); 第二个方法是SringBuffer但在j2me中它没
If string is an alias of String in the .net framework为什么会发生这种情况,我应该如何解释它: type JustAString = string
我有两个列表(或字符串):一个大,另一个小。 我想检查较大的(A)是否包含小的(B)。 我的期望如下: 案例 1. B 是 A 的子集 A = [1,2,3] B = [1,2] contains(A
我有一个似乎无法解决的小问题。 这里...我有一个像这样创建的输入... var input = $(''); 如果我这样做......一切都很好 $(this).append(input); 如果我
我有以下代码片段 string[] lines = objects.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.No
这可能真的很简单,但我已经坚持了一段时间了。 我正在尝试输出一个字符串,然后输出一个带有两位小数的 double ,后跟另一个字符串,这是我的代码。 System.out.printf("成本:%.2
以下是 Cloud Firestore 列表查询中的示例之一 citiesRef.where("state", ">=", "CA").where("state", "= 字符串,我们在Stack O
我正在尝试检查一个字符串是否包含在另一个字符串中。后面的代码非常简单。我怎样才能在 jquery 中做到这一点? function deleteRow(locName, locID) { if
这个问题在这里已经有了答案: How to implement big int in C++ (14 个答案) 关闭 9 年前。 我有 2 个字符串,都只包含数字。这些数字大于 uint64_t 的
我有一个带有自定义转换器的 Dozer 映射: com.xyz.Customer com.xyz.CustomerDAO customerName
这个问题在这里已经有了答案: How do I compare strings in Java? (23 个回答) 关闭 6 年前。 我想了解字符串池的工作原理以及一个字符串等于另一个字符串的规则是
我已阅读 this问题和其他一些问题。但它们与我的问题有些无关 对于 UILabel 如果你不指定 ? 或 ! 你会得到这样的错误: @IBOutlet property has non-option
这两种方法中哪一种在理论上更快,为什么? (指向字符串的指针必须是常量。) destination[count] 和 *destination++ 之间的确切区别是什么? destination[co
This question already has answers here: Closed 11 years ago. Possible Duplicates: Is String.Format a
我有一个Stream一个文件的,现在我想将相同的单词组合成 Map这很重要,这个词在 Stream 中出现的频率. 我知道我必须使用 collect(Collectors.groupingBy(..)
我是一名优秀的程序员,十分优秀!