Advice on Segmentation Fault, using gdb effectively, C Programming (newbie) - c

I am having a problem with a segmentation fault working in C, and I cannot figure out why this is occurring. I think it has something to do with misuse of the fget(c) function.
while((ch = fgetc(fp))!= EOF) {
printf("Got inside first while: character is currently %c \n",ch); //**********DELETE
while(ch != '\n') {
char word[16]; //Clear out word before beginning
i = i+1; //Keeps track of the current run thru of the loop so we know what input we're looking at.
while(ch != ' ') {
printf("%c ",ch); //**********DELETE
//The following block builds up a character array from the current "word" (separated by spaces) in the input file.
int len = strlen(word);
word[len] = ch;
word[len+1] = '\0';
printf("%s",word);
ch = fgetc(fp);
}
//The following if-else block sets the variables TextA, TextB, and TextC to the appropriate Supply Types from the input.
//This part may be confusing to read mentally, but not to trace. All it does is logically set TextA, B, and C to the 3 different possible values SupplyType.
if(word!=TextB && word!=TextC && i==1 && TextB!="") {
strcpy(TextA,word);
}
else if(word!=TextA && word!=TextC && i==1 && TextC!="") {
strcpy(TextB,word);
}
else if(word!=TextB && word!=TextA && i==1) {
strcpy(TextC,word);
}
switch(i) {
case 1:
if(TextA == word) {
SubTypeOption = 1;
}
else if(TextB == word) {
SubTypeOption = 2;
}
else if(TextC == word) {
SubTypeOption = 3;
}
break;
case 2:
//We actually ultimately don't need to keep track of the product's name, so we do nothing for case i=2. Included for readibility.
break;
case 3:
WholesalePrice = atof(word);
break;
case 4:
WholesaleAmount = atoi(word);
break;
case 5:
RetailPrice = atof(word);
break;
case 6:
RetailAmount = atoi(word);
break;
}//End switch(i)
ch = fgetc(fp);
}//End while(ch != '\n')
//The following if-else block "tallys up" the total amounts of SubTypes bought and sold by the owner.
if(SubTypeOption == 1) {
SubType1OwnersCost = SubType1OwnersCost + (WholesalePrice*(float)WholesaleAmount);
SubType1ConsumersCost = SubType1ConsumersCost + (RetailPrice *(float)RetailAmount);
}
else if(SubTypeOption == 2) {
SubType2OwnersCost = SubType2OwnersCost + (WholesalePrice*(float)WholesaleAmount);
SubType2ConsumersCost = SubType2ConsumersCost + (RetailPrice *(float)RetailAmount);
}
else if(SubTypeOption == 3) {
SubType3OwnersCost = SubType3OwnersCost + (WholesalePrice*(float)WholesaleAmount);
SubType3ConsumersCost = SubType3ConsumersCost + (RetailPrice *(float)RetailAmount);
}
}//End while((ch = fgetc(fp))!= EOF)
Using gdb (just a simple run of the a.out) I found that the problem is related to getc, but it does not tell which line/which one. However, my program does output "Got in side the first while: character is currently S". This S is the first letter in my input file, so I know it is working somewhat how it should, but then causes a seg fault.
Does anyone have any advice on what could be going wrong, or how to debug this problem? I am relatively new to C and confused mostly on syntax. I have a feeling I've done some small syntactical thing wrong.
By the way, this snippet of the code is meant to get a word from a string. Example:
Help me with this program please
should give word equaling "Help"
Update: Now guys I am getting kind of a cool error (although cryptic). When I recompiled I got something like this:
word is now w S
word is now w Su
word is now w Sup
... etc except it goes on for a while, building a pyramid of word.
with my input file having only the string "SupplyTypeA 1.23 1 1.65 1" in it.
UPDATE: Segmentation fault was fixed (the issue was, I was going past the end of the file using fgetc() ). Thanks everyone.
If anyone still glances at this, could they help me figure out why my output file does not contain any of the correct numbers it should? I think I am probably misusing atof and atoi on the words I'm getting.

Make sure you compile the program with -g -O0 options
Next step through the program line by line in GDB, watch and understand what your program is doing. Look at the various variables. This is the essential debugging skill.
WHen it dies type the command 'k' this will give you a stack trace the last line of the trace will have the failing line number, but you know that anyway because you were on the line shen you did a step command

There is no "fget" in good old C, but maybe you're using a more modern version that has something named "fget". Most likely, you meant to use "fgetc". When a C I/O function starts with "f", it usually wants a FILE* handle as an argument, as "fgetc" does. Try using "fgetc" instead, after reading the documentation for it.

Related

Variable loses its value C

I'm working on this project where a user has to guess a word (wordToGuess) and he has a number of attempts.
The problem is that the variable "wordToGuess" loses its value when the code arrives in the point marked ("HERE LOSES ITS VALUE). I don't know how to solve this problem, I've tried in many ways. Thank u for your help!
(checkExistence is a function that checks if the word is present in the dictionary)
void newGame(node* head){
char wordToGuess[10];
char attempt[10];
int numberOfAttempts = 0;
if (scanf("%s" , wordToGuess) != 1){
printf("error1");
}
getchar();
if (scanf("%d", &numberOfAttempts) != 1){
printf("error2");
}
getchar();
while(numberOfAttempts > 0){
if (scanf("%s", attempt) != EOF){
if (attempt[0] != '+'){
if (checkExistence(head, attempt) == false){
printf("not_exists\n");
}else{
if (strcmp(wordToGuess, attempt) == 0){
printf("ok\n");
return;
}else{
//code
numberOfAttempts--;
}
}
}else{
if (attempt[0] == '+' && attempt[1] == 's'){
//HERE LOSES ITS VALUE
}else if (attempt[0] == '+' && attempt[1] == 'i'){
//other code
}
}
}else{
printf("ko");
return;
}
}
return;
}
Here a test case:
2rj9R (wordToGuess)
18 (numerAttemps)
DP3wc (attempt)
7PGPU (attempt)
2rz9R (attempt)
+print_list (from this point I lose the value of wordToGuess)
2rj9R (attempt)
As the others have point, you're probably causing a buffer overflow in your attempt buffer which overwrites your wordToGuess buffer since your attempt and wordToGuess buffer is stored like this in your memory:
<attempt buffer> | <word To Guess>
You have two possible fixes for this (as the comments have said...):
A little fix would be to set a limit of how many characters should be read from stdin to scanf like this:
scanf("%9s" , wordToGuess) // you need 9, because your buffer can store up to
// 10 bytes but don't forget that `scanf` is also
// addinng `\0` for you!
and don't forget to flush the rest of the user input if you want that the user should be only able to insert at most 9 characters!
Increase the buffer size of your attempt (and wordToGuess) buffer but also add those read-limits for scanf which is described in the first point.
At the indicated point of the code where wordToGuess appears to lose its value, it is a dead variable. If you're looking at optimized code in a debugger, you may find that the variable doesn't exist there any more.
At a given point in a program, a dead variable is one which is never used past that point. All control flows out of that point reach the termination of that code, without ever using the variable again. Simple example:
{
int x = 3;
// x is live here: there is a next reference
printf("%d\n", x);
// x is now dead: it is not referenced after the above use
printf("foo\n");
}
In the generated code, the compiler may arrange to re-use the resources tied to a dead variable as soon as it is dead: give its register and memory location to something else.
In the debugger, if we put a breakpoint on the printf("foo\n") and try to examine x, we might get a strange result.
To have the best chance of seeing the expected result (that x still exists, and is retaining its most recent value), we have to compile with optimizations disabled.

Why does my function return 0 instead of the number of lines in a file?

I have written a function that is supposed to read the number of sentences in a .txt file, but when the function is called and done, it gives me a value of 0.
This program over all has 3 more functions to figure out different properties of the file and I have them working great. This one is laid out the same way I wrote my other functions just looking for some advice on why I am getting 0 as my number of sentences.
void ptrCntS (FILE* sp1, int sCount)
{
char sentence = 'O';
int myChr;
if (!(sp1 = fopen("Hello.txt", "r")))
{
printf("error opening Hello.txt");
return(1);
}
while ((myChr = fgetc(sp1)) != EOF)
{
if ('.')
{
sentence ='O';
}
else if (sentence == 'O')
{
sCount++;
sentence = 'I';
}
}
fclose(sp1);
printf ("Total number of sentences are:\t%d", sCount);
return;
}
instead of return use return(sCount);
and assign the return value to some int variable in calling function
like
int sentCount;
.
.
.
sentCount=ptrCntS (param1,param2);
if ('.') is always true, thus else... code never reached. Use if( myChr == '.' ) instead.
Function compiles now and runs properly. This function is being called from a switch in a previous function where I had my addresses set and included my print statement for the totals so that I would not have to write another function in the end to call on all my counts and print their results. Instead I set my case 'A': to call all of my counting functions(in this case that is what the original code is) and than display my results. I am sorry for any lengthiness or my hard to understand writing I am new to the C language and I am having a hard time grasping the literature but making some process on understanding the syntax.

Why this program always shows U at the end

I have created following C code for encrypt words.(caesar cipher) when I run this it prints U at the end always.if you run this you will see it.
#include<stdio.h>
int main(void){
int x;
char en[100];
fgets(en,100,stdin);
for(x=0;x<100;x++){
if(en[x]=='\0'){
break;
}
en[x]=((en[x]-71-3)%26)+97;
}
printf("%s\n",en);
}
fgets places a '\n' character before the '\0' at the end of the buffer. So if you don't want to encrypt it, loop until the condition below is satisfied:
if (en[x] == '\0' || en[x] == '\n') break;
To be rigorous, the actual reason why you are getting a U is due to the fact that \n has ASCII code 10. Thus, (10-74)%26 + 97 = 85, which is the ASCII code for U.
if (en[x] == '\0' || en[x] == '\n') break;
The above condition should solve your problem.
some reading for the \0 and \n is given in the following link
he is a output of the "trail" run which give more insight on a step by step way
trial
*rial
rial
q(ial
qial
qoal
qoal
qofl
qofl
qofx"
qofx
qofxi?
qofxi?
qofxiU

+= and incremental growth give two different values in C

I have a chunk of code that is measuring the length of a block of text. I need the length of a gap of an unknown number of N inserted within the text (which consists of G, A, C, and T only) as well as the total length of the text block containing the gap(s). I am working one character at a time via a fgetc() and I devised two different ways to calculate the values, but they are giving me vastly differing results.
Method A:
...
} else if (in != '\n') {
scafLength++;
if (in == 'N') {
//Read entire gap
while ((in != 'G') && (in != 'A') && (in != 'C') && (in != 'T') && (in != '>')) {
if (in != '\n'){
gapLength++;
scafLength++;
}
in = fgetc (inFile);
//If it's at the end of the file
if (feof (inFile)) {
break;
}
}
...
Do stuff
...
//Reset for next gap and allow normal processing of next character after the gap
gapLength = 0;
fseek (inFile, -1, SEEK_CUR);
}
}
Method B:
...
} else if (in != '\n') {
scafLength++;
if (in == 'N') {
//Read entire gap
while ((in != 'G') && (in != 'A') && (in != 'C') && (in != 'T') && (in != '>')) {
if (in != '\n'){
gapLength++;
}
in = fgetc (inFile);
//If it's at the end of the file
if (feof (inFile)) {
break;
}
}
scafLength += gapLength - 1;
...
Do stuff
...
//Reset for next gap and allow normal processing of next character after the gap
gapLength = 0;
fseek (inFile, -1, SEEK_CUR);
}
}
> is a character used to denote a new scaf. This is the only area where scafLength and gapLength are altered, except to set them back to 0 for a new gap/scaf. Now, I expected an off-by-one in method A, which is why I made method B, but the numbers I'm getting are way off. Method A is giving me 16,777,216 as the longest scaf while Method B gives me 23,080,784. The real longest scaf (verified by multiple other programs) is 23,428,386 and there are not 5 million gaps to account for a fencepost error (the most is 180).
I'm curious why would these two approaches give such drastic differences? Also, if anyone can see a mistake I'm making, I'd appreciate it being pointed out.
EDIT: From the first few comments I need to clarify, the gapLength is reset to 0 after it serves it's purpose in the same else if (). I've updated the code.
In the first version it looks like you only incrementing scafLength when (in != '\n') but in the second version you continually add the value of gapLength - 1 whenever you enter the outer if-block and not just when you enter the inner (in != '\n')
Presumably the value of gapLength isn't reset and therefore the second version grows faster.
As your code is incomplete it's really hard to say, so consider this a guess.
Turns out the issue was with my variable type caused by my compiler. gapLength and scafLength were originally declared as int. Having run out of options, I switch them to long and the code performs perfectly. Apparently my compiler has the short int limit of 32,768.

Parameters inside the function

I have a work to do in which I have to keep a loop inside the function expecting the following parameters:
-"i" to insert
-"s" to search
-"q" to quit
How do I keep this loop? I've looked up some options and it seems to be possible using a while or a switch, but I am not sure which is the best way to read those chars (with a fscanf perhaps?). I am also not sure how to read the things after the parameter "i" as the input would be "i word 9", so after detecting the i to insert I have to read a string and an int.
Anyone has any idea how to do this? I am sorry is this seems simple, but I am new to programming.
edit: Here is what I have so far
while (loop) {
fscanf(stdin,"%c",&par);
if (strcmp(&par,"i")){
scanf("%s %d",palavra,p);
raiz = insere(raiz,&palavra,p);
}
else if (strcmp(&par,"b")){
scanf("%s",palavra);
busca(raiz,&palavra);
}
else if (strcmp(&par,"q"))
loop = 0;
}
edit 2: This is what I have now, I am having problems reading the string and integer when the parameter is i, somehow it crashes the function
while (1) {
c = getchar();
if (c == 'f')
break;
else if (c == 'i'){
fscanf(stdin,"%s",&palavra);
scanf("%d",&p);
raiz = insere(raiz,palavra,p);
}
else if (c == 'b') {
scanf("%s",palavra);
busca(raiz,palavra);
}
}
Thanks in advance!
The code you have doesn't look too bad compared to what I believe you want. You can replace the "while (loop)" with "while (1)" and then your exist code "loop = 0;" with "break;" which is a bit more standard way of doing things. Also "fscanf(stdin..." is the same as "scanf(..." ... scanf will read from stdin by default. You might want to check the docs for strcmp because it returns 0 for an exact match and I don't think that will do what you want in your 'if' statements. You should be able to use scanf to read in the values you want, is it giving you an error?
You are using 3 separated scans. That means you can't input this "i word 9", but input one command or parameter at the time separated by EOL(pressing enter).. i, enter, word, enter, 9, enter ... Then the function should actually get further in those "if"s. With those scans you also should consider printing information about expected inputs ("Choose action q/i/f")
And I would recommend using something to test those inputs.
if (scanf("%d", &p) == 0) {
printf("Wrong input");
break;
}

Resources