+= and incremental growth give two different values in C - 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.

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.

curses move backwards accounting for previous lines

Is there any way to move the cursor backwards while accounting for previous lines, i.e. when the cursor goes back from the beginning of the line it goes to the last non-empty character of the previous line?
So there's no built in method for this, so I had to write my own
void backspace(){
int x,y;
getyx(stdscr,y,x);
if(x == 0) {
if( y == 0 ) {
return;
}
x = getmaxx(stdscr) - 1;
move(--y,x);
char ch = ' ';
while(ch == ' ' && x != 0){
move(y,--x);
ch=inch();
}
} else {
move(y,x-1);
}
delch();
}
Note that I have removed some irrelevant file I/O related code that was in this method.
You can do that easily in a curses (full-screen) application (by reading the characters from the virtual screen using winch or win_wch), but would find it much harder in a termcap/terminfo low-level application because there is no portable method for reading directly from the terminal's screen.

If you have to put breaks in the if statements, why do we need to bother with conditions in the while operation?

This is just a general question really.
I wrote this originally
do
{
scanf("%i", &Carselect);
if (Carselect == 1)
{
mass = 1100;
velomax = 200;
}
else if (Carselect == 2)
{
mass = 1888;
velomax = 415
}
else if (Carselect == 3)
{
mass = 18000;
velomax = 129;
}
else
{
printf("Error in input. Please enter 1, 2 or 3.\n");
}
}
while (Carselect != 1 || Carselect != 2 || Carselect != 3);
And I got stuck in the loop. I put breaks in the statements for the valid conditions and that allowed me to get out, like this
do
{
scanf("%i", &Carselect);
if (Carselect == 1)
{
mass = 1100;
velomax = 200;
break;
}
else if (Carselect == 2)
{
mass = 1888;
velomax = 415;
break;
}
else if (Carselect == 3)
{
mass = 18000;
velomax = 129;
break;
}
else
{
printf("Error in input. Please enter 1, 2 or 3.\n");
}
}
while (Carselect != 1 || Carselect != 2 || Carselect != 3);
but I thought that the conditions for while were repeat conditions, so as soon as Carselect equals 1, 2 or 3 it will exit the loop. If you have to put breaks in the if statements, why do we need to bother with conditions in the while operation?
What is there, on the machine level or otherwise, that requires this seemingly trivial bit of logic?
Edit (as the question's title is changed):
The checking condition in the while/do-while loop is the one that is primarily checked to determine if the program is to stay in or to get out of the while/do-while loop - not the break statement.
The break statement is normally used if:
you want to get out of the while/do-while block before it is executing every statement in the block or
when certain exceptional termination condition is reached before you loop through your entire loop iteration or
You create an infinite loop and you capture an error which makes you unable to continue the loop or
Some other other cases which I might not be aware of...
Essentially, break-statement is not normally used to terminate the while/do-while block as long as the program follows (for lack of better term) "standard/main" path in the loop block.
In contrast, condition in the while/do-while loop is used to terminate the loop when the program follows "standard/main" path in the loop block.
Original:
You should change your inequality check (!=) into NOT equality check (==).
while (!(Carselect == 1 || Carselect == 2 || Carselect == 3));
This is because what you really want is for the loop to continue as long as
the Carselect is not (1 or 2 or 3)
Alternatively, you could change the or operator (||) to and operator (&&) which results in the same logic:
while (Carselect != 1 && Carselect != 2 && Carselect != 3);
the Carselect is not 1 and not 2 and not 3
In C break takes you to the statement immediately following } of the containing block, and continue takes you to to the statement immediately following { of the containing block. Both are useful in a long block, for example if an error condition occurs, or if a simpler input is detected, and not all the processing of the complete block is required, but you want to continue and get the next input.

Read from a certain part of a file PIC32MX

I am using PIC32MX in a design made by myself and everything is working perfectly.
Now I am trying to implement a feature which is basically read from a file sequentially until I found a certain frame of characters, so I am doing:
while( (readedBytes = FSfread((void *)&c,sizeof(char),1,ephpubData->filetouart) != 0) && G_RUNNING && ephpubData->readedBytes < 2520){
privData->txBuffer[privData->txBufferPos++] = c;
ephpubData->readedBytes = ephpubData->readedBytes + readedBytes;
if (privData->txBufferPos == TX_BUFFER_SIZE){
if (verifyDate (task) == 1){
*gpsState = GPS_STATE_VERIFY;
ephpubData->count++;
break;
}
FSfseek(ephpubData->filetouart , ephpubData->readedBytes , SEEK_SET);
privData->txBufferPos = 0;
}
}
For the first time when it finds the frame (using the verifyDate function) everything is ok and it goes to break sentence.
When it comes to read the second time in the while loop (after close/reopen the file and doing other things in the code) it goes to the first position again.
So I want to save the the latest position found until the break sentence. I already tried to use the seek function for every while iteration
while( (readedBytes = FSfread((void *)&c,sizeof(char),1,ephpubData->filetouart->seek) != 0) && G_RUNNING && ephpubData->readedBytes < 2520)
but it gave me an error.
Sorry folks but I found the bug.
Somewhere in the code I was doing:
FSfseek( ephpubData->filetouart , 0 , SEEK_SET );
Which sets the reading position to 0.

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

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.

Resources