我在USACO上写小程序问候。
问题发布为http://usacotraining.blogspot.co.uk/2013/09/problem-112-greedy-gift-givers.html
这是我的代码:
/*
ID: xin.sun2
LANG: C
TASK: gift1
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int searchIndex(char *list[], char* s, int size) {
for (int i = 0; i < size; i ++) {
if (strcmp(list[i], s) == 0) {
return i;
}
}
return -1;
}
int main() {
freopen("gift1.in", "r", stdin);
freopen("gift1.out", "w", stdout);
int num_people = 0;
scanf("%d", &num_people);
char *nameList[num_people] = malloc(num_people*100*sizeof(char));
int money[num_people];
memset(money, 0, num_people*sizeof(int));
for (int i = 0; i < num_people; i++)
scanf("%s", nameList[i]);
char* this_people = malloc(100*sizeof(char));
while (scanf("%s", this_people) != EOF) {
int amount, num_giving, people_index;
people_index = searchIndex(nameList, this_people, num_people);
scanf("%d", &amount);
scanf("%d", &num_giving);
money[people_index] -= amount/num_giving*num_giving;
int giving_amount = amount/num_giving;
for (int i = 0; i < num_giving; i++) {
char* p = malloc(100*sizeof(char));
scanf("%s",p);
int this_index = searchIndex(nameList, p, num_people);
money[this_index] += giving_amount;
}
}
for (int i = 0; i < num_people; i++) {
printf("%s %d\n", nameList[i], money[i]);
}
return 0;
}
编译.c文件时没有问题,但是当我执行文件时。它显示了分段错误11.我确实尝试使用gdb,结果是
Program received signal SIGSEGV, Segmentation fault.
0x00007fff96b17908 in ?? ()
我有两个问题: 1.我的代码(算法)有什么问题?它可能是语法问题,因为我对c编程很新 2.为什么gdb显示??()而不是主要问题所在的行号。我是否以错误的方式使用gdb?
全部谢谢!
更新
我已经解决了没有为数组和char签名空间的问题。 但是存在编译错误
null.c:27:8: error: variable-sized object may not be initialized
char *nameList[num_people] = malloc(num_people*100*sizeof(char));
我对初始化字符串数组的正确方法以及如何将字符串数组作为参数传递给函数有疑问。
答案 0 :(得分:2)
char* this_people;
while (scanf("%s", this_people) != EOF) {
和
char* p;
scanf("%s",p);
是错误的,this_people和p指向无处,而scanf使用这个“无处”作为输入缓冲区。使用malloc()来分配一些内存,或者使用p作为数组。 (如果用户输入的内容比你提供的空间长,你仍然会遇到问题,但是当你正在学习时,直到以后才会出现问题。)
当您遇到这样的问题时,gdb命令bt
就是您的朋友。它显示了崩溃后从哪里调用了哪些函数。
对于namelist数组,您要使用:
定义:
char **namelist;
namelist=malloc(num_people*sizeof (char *));
或者,但这需要“新的”编译器,因为它不是旧的C规范:
char *namelist[num_people];
然后,在每两个案例中:
for (i=0; i<num_people; i++)
namelist[i]=malloc(100);
(你应该检查malloc是否返回NULL并抛出错误,但为了简洁,我省略了它。)
答案 1 :(得分:1)
char* this_people;
while (scanf("%s", this_people) != EOF) {
this_people需要存储空间。成为
的形式char this_people[100]; //or some desired maximum storage
while (scanf("%s", this_people) != EOF) {
此外,
char *nameList[num_people];
分配一堆类型为char *
的指针。没有任何存储空间。
答案 2 :(得分:1)
发生分段错误是因为您试图写入内存并不是由您自己分配的,正如其他答案所指出的那样。要解决这些问题,您有几个选项,可以将它们定义为固定长度数组,通过调用malloc()
为它们动态分配内存,或者使用scanf("%ms", &p)
并让glibc为内存分配你。
GDB显示?? ()
而不是行号和功能名称,因为它没有足够的信息来显示它们。要解决此问题,您需要使用-g
编译程序(我假设您正在使用gcc
)并为您的程序所需的系统库(本例中为glibc)安装调试信息包。如果您使用的是Fedora或CentOS,则可以通过debuginfo-install glibc
为glibc安装调试信息包。
答案 3 :(得分:0)
你的问题在那里:
for (int i = 0; i < 5; i++)
scanf("%s", nameList[i]);
指针nameList[i]
尚未与任何已分配的内存位置相关联。您需要执行以下操作:
char *nameList[num_people];
for (int i=0; i<num_people; i++)
nameList[i] = malloc(30*sizeof(char)); // or any size you choose
同样代表:
char* this_people;
另外,要在gdb
中获得精确的详细信息,您需要使用-g
标志编译程序(如果使用GCC)。