Infinite loop due to wrong condition in C - c

Hey guys i'm new to C and i'm trying to learn something by myself.
So here's the question: i have an infinite loop and i don't understand why.
I've already checked other topics but i didn't understand, actually.
Here's the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/**
* Auto-generated code below aims at helping you parse
* the standard input according to the problem statement.
**/
int main()
{
int n,i=0; // the number of temperatures to analyse
scanf("%d", &n); fgetc(stdin);
char temps[257]; // the n temperatures expressed as integers ranging from -273 to 5526
fgets(temps, 257, stdin); // the n temperatures expressed as integers ranging from -273 to 5526
int temp[257]={0};
char *pointer;
pointer= temps;
while(*pointer != NULL){
int i=0, sign=1;
if(*pointer == '-'){
sign=-1;
pointer++;
}
while(*pointer != 32) { //infinite loop!
if(*pointer >='0' && *pointer<='9'){
temp[i]= (temp[i] *10) + ((*pointer) -'0');
temp[i]= temp[i]*sign;
printf("try");
}
}
printf("%d\n", temp[i]); //verifying temps != 0
pointer++;
i++;
}
return 0;
}
I really don't understand why.
Anyway, the aim of the program is: "Write a program that prints the temperature closest to 0 among input data. If two numbers are equally close to zero, positive integer has to be considered closest to zero (for instance, if the temperatures are -5 and 5, then display 5)."
You may need it.
Thank you in advance.

In the loop:
while(*pointer != 32)
you never change pointer or *pointer within the loop body. So if this loop is entered once then it can never exit.
You probably meant to have a pointer++ somewhere, and perhaps the loop condition should actually be while(*pointer >='0' && *pointer<='9') (what if the string has some numbers, then a letter, then some numbers?)
However bear in mind that this loop will also have to check for end-of-string ('\0') and exit the outer loop correctly if it does hit that (instead of doing pointer++ and going past the terminator as you do in the case of the input being just -).

Ok, I actually understood. Thank you.
So now this is the loop
while(*pointer != 32 || *pointer != '\0') {
if(*pointer >='0' && *pointer<='9'){
temp[i]= (temp[i] *10) + ((*pointer) -'0');
temp[i]= temp[i]*sign;
pointer++;
}
}
Now it gives me values, but at a certain point, it becomes infinite.
The rest of the code is the same.
EDIT: i modified the loop condition with while(*pointer >='0' && *pointer<='9') and it's not infinite!
But doesn't work. There may be a logical mistake.
EDIT 2: i found it. i've initialized i=0 in the while loop and of course it kept updating the same temp[i].
Thank you again.

Related

C - Can't stop program using while and logical operator

I'm just starting learning C but I really don't know what am I doing wrong. I wrote this code, and it was supposed to stop reading numbers when it receives a negative number. I have wasted a lot of time trying to figure out what it is wrong, and I still don't know what it is.
#include<stdio.h>
int main(){
const int qtd = 3;
float ent[qtd];
int i = qtd;
printf("Digite os numeros\n");
do{
scanf("%f", &ent[i]);
i--;
}while (ent[i] >= 0 && i >= 1);
printf("\n\n\n\nPressione 'Enter' para sair");
fflush(stdin);
getchar();
return 0;
}
The problem is with the index of ent that you check for being negative. It's ent[i], but it is after i has been decremented, so you are reading the location that has not been written yet by scanf.
To fix the problem, change the code to use the prior location, i.e.
do {
...
} while (ent[i+1] >= 0 && ...);
There are several other problems with your code, all coming from the assumption that array indexes start at 1. In C, however, the initial index is zero, not one, so the correct check should be
do {
...
} while (ent[i+1] >= 0 && i >= 0);
In addition, i should be initialized to int i = qtd-1; to avoid writing past the end of allocated array.

Using recursion to find a 2D maze path. Seg Faulting. C

I am having trouble finishing this program. The assignment is to use recursion to find a path through a maze composed of X's and O's. The path one can go through is designated by the O's The maze is stored as a text file.
Here is a sample maze:
XOXXXXXX
XOXXXXXX
XOOOOXXX
XXXXOXXX
XXXXOOXX
XXXXXOXX
XXXXXOOO
XXXXXXXO
And here is my attached code. I am attatching all of my code, but I would not like to be told exactly how to do it, I am here to learn :-).I do believe my problem is with not accounting for the same O i just looked for, but im not 100% sure. Thanks!!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int find_path(char maze[8][8], int coorx, int coory);
int main(int argc, char *argv[])
{
char maze[8][8];
int i=0,j=0;
FILE *fp;
fp = fopen(argv[1], "r");
for(i=0;i<9;i++)
for(j=0;j<9;j++)
fscanf(fp,"%c",&maze[i][j]);
fclose(fp);
printf("%c", maze[2][3]);
return 0;
}
int find_path(char maze[8][8], int coorx, int coory)
{
//if((maze[coorx][coory]!= 'O') && (coorx >=0) && (coorx < 8) && (coory >=0) &&
//(coorx < 8)){
if(find_path(maze, coorx + 1, coory) == 'O'){
printf("(%d,%d)",coorx, coory);
}
else if(find_path(maze, coorx - 1, coory) == 'O'){
printf("(%d,%d)",coorx, coory);
}
else if(find_path(maze, coorx, coory + 1) == 'O'){
printf("(%d,%d)",coorx, coory);
}
else if(find_path(maze, coorx, coory - 1) == 'O'){
printf("(%d,%d)",coorx, coory);
}
return 0;
}
You have this declaration
char maze[8][8];
And loop like this
for(i=0;i<9;i++)
That is, you loop from zero to eight (inclusive) which is nine indexes. For an array of only eight entries.
This means you will write out of bounds of the arrays, leading to undefined behavior.
Either change your loop condition, or increase your array sizes.
find_path doesn't have a clear base case, since the if at the beginning is commented out. The very first thing it does, is call itself again with cell to the right. And the first thing that call does, is call itself again, with the cell to the right of that. There's nothing to stop it from just falling right off the end of the array, at which point it's just dumb luck you haven't caused missiles to launch somewhere.
Even if that weren't the case, there's nothing keeping it from getting stuck between a cell with a wall to the right, and the cell just to the left of it. You try to go right, but can't, so you go left. Next step, you can go right again, so you do. Repeat for all eternity (or at least til you eat up your stack).

C loop won't exit

Good-morning one and all!
This is going to end up being one of those blindingly-easy questions in hindsight, but for the life of me I'm stumped. I'm going through some of the exercises in The C Programming Language, and I've managed to write some code to initialize a loop. After some Googling, I found better ways of initializing a loop to 0, but I don't understand why the loop that I wrote to do it doesn't finish. I've used the debugger to find out that it's because the 'c' variable never reaches 50, it gets to 49 and then rolls over to 0, but I can't figure out why it's rolling over. The code is attached below, does anyone know what's going on here?
#include <stdio.h>
#define IN 1
#define OUT 0
/* Write a program to print a histogram of the lengths of words in
itsinput. */
main()
{
int c=0;
int histogram[50]={0}
int current_length=0;
int state=OUT;
//Here we borrow C so we don't have to use i
printf("Initializing...\n");
while(c<51){
histogram[c] =0;
c=c+1;
}
c=0;
printf("Done\n");
while( (c=getchar()) != EOF){
if( (c==32 || c==10) && state==IN ){
//End of word
state=OUT;
histogram[current_length++];
}else if( (c>=33 && c<=126) && state==OUT ){
//Start of word
state=IN;
current_length=0;
}else if( (c>=33 && c<=126) && state==IN ){
//In a word
current_length++;
} else {
//Not in a word
//Example, " " or " \n "
;
}
}
//Print the histogram
//Recycle current_length to hold the length of the longest word
//Find longest word
for( c=0; c<50; c++){
if( c>histogram[c] )
current_length=histogram[c];
}
for( c=current_length; c>=0; c--){
for( state=0; state<=50; state++){
if( histogram[c]>=current_length )
printf("_");
else
printf(" ");
}
}
}
It's because histogram[c] = 0 writes past the histogram memory when c = 50. So essentially histogram[50] overwrites c and makes it 0.
This happens because arrays start from 0 in C. So the last valid index in a 50-element array is 49.
Technically, while interesting and exploitable you can't rely on this. It's a manifestation of undefined behavior. The memory could easily have another layout causing things to "just work" or do something funnier.
histogram has 50 elements: from index 0 to index 49.
You attempt to write to index 50. ALL BETS ARE OFF
do
while (c < 50)
or, to avoid magic constants
while (c < sizeof histogram / sizeof *histogram)
You are accessing elements 0 to 50 in histogram, which only contains elements 0 to 49 (C/C++ use zero-indexing, so the maximum element of an array will always be size-1).
To avoid errors like this, you could define the histogram size as a constant, and use that for all operations relating to the histogram array:
#define HISTOGRAM_SIZE 50
Or (only works for C99 or C++, see below comment):
const int HISTOGRAM_SIZE = 50;
Then:
int histogram[HISTOGRAM_SIZE];
And:
while(c<HISTOGRAM_SIZE)
'#define' is a C-preprocessor statement, and will be processed before compilation. To the compiler, it will just look as if you've written 50 everywhere where HISTOGRAM_SIZE is used, so you wont get any extra overhead.
'const int' gives you a similar solution, which in many cases will give the same result as with the define (I'm not 100% certain under which circumstances though, others are free to elaborate), but will also give you the added bonus of type-checking.

strncmp function does not stop checking at n characters?

My program compares the 2 strings entirely and does not stop once n number of characters are reached? Why does this happen?
int strncompare (const char* mystring1,const char* mystring2, int number)
{
int z;
z = number - 1;
while ((*mystring1==*mystring2) && (*mystring1 != '\0') && (*mystring2 != '\0'))
{
*mystring1++;
*mystring2++;
if ((*mystring1 == mystring1[z]) && (*mystring2 == mystring2[z]))
{
break;
}
}
return (mystring1++ - mystring2++);
}
Because you don't stop when you've compared number characters.
There are several ways to do this, but I would recommend changing your loop condition to
while (*mystring1 && *mystring2 && *mystring1 == *mystring2 && number-- > 0)
Also remove
if ((*mystring1 == mystring1[z]) && (*mystring2 == mystring2[z]))
{
break;
}
Because, although it seems like that was your attempt at making it stop, it's coded wrong; you don't care if the characters are the same, you only care if you've compared number characters. Also you use && which makes the condition even more restrictive than it already was.
Also change
*mystring1++;
*mystring2++;
To
mystring1++; // or better, ++mystring1
mystring2++; // or better, ++mystring2
The * dereferences the pointer but you're not doing anything with it so it's pointless (pun intended).
You also can remove the ++ from these:
return (mystring1++ - mystring2++);
So it would be
return mystring1 - mystring2;
However, that is undefined behaviour when the two pointers point to different arrays (which they probably always will). You need to be doing something else. What? I don't know because I don't know what your function should return.
You have no condition in your function that examines number, or z that you derive from it. What would make it stop?
Why don't you simply decrement number and break when it reaches 0 assuming the loop hasn't broken by that point
You should update z on each iteration and then check if it reaches zero, try adding this to your code:
if (z == 0)
break;
else
z -= 1;
Also, that check you have there is really faulty, if it worked it could stop at an unwanted time, for example on the strings "abcdec" and "xxcddc", where number = 6, it would stop at 3, because the characters at those indexes are the same as those on index 6.
Re-read your code very thoroughly and make sure you really understand it before taking any of these answers into account.
This will walk until it finds a difference, or the end of the string.
while(n > 0) {
if(*str1 != *str2 || *str1 == '\0'){
return *str1 - *str2;; //they're different, or we've reached the end.
}
++str1; //until you understand how ++ works it's a good idea to leave them on their own line.
++str2;
--n;
}
return 0;// I originally had *str1 - *str2 here, but what if n came in as zero..
the problem with the z compare is it's a moving target.
think of [] as a + sign.. mystring1[z] could be represented like this *(mystring1 + z)
That means the line above ++mystring1; (as it should be) is moving the pointer and thus moving where z is looking..
It might help to think of pointers as address on a street.. when you ++ you move up a house..
Say z = 1.. and the house that mystring1 points at is yours, and z is your neighbor. add one to the house you're looking at, and mystring1 is now pointing at your neighbor, and z is pointing at his neighbor because z is still saying what your pointing at + 1.
Thanks all...I fixed the error...added another condition to the while loop.
int i;
i=0;
z = number - 1;
while((*mystring1==*mystring2) && (*mystring1 !='\0') && (*mystring2 !='\0') && (i<z))
and then incrementing i till it comes out of this loop.

Averaging 3 integers

My assignment is to fix the code. I have my edited code below and the original code below that. I figure I still have a few errors in here. My error checking doesnt seem to work, and I am not sure if my getchar() function is written or working properly.
Please assume I know nothing becasue that is fairly accurate.
The code compiles, but the answer is always 2. I am about 4 hours into this piece of code with 3 more to work after this.
My code
#include <stdio.h>
double get_number(double num);
main () {
double n1,n2,n3;
double average;
printf("\nCompute the average of 3 integers\n");
printf("--------------------------------\n");
n1 = get_number(1);
n2 = get_number(2);
n3 = get_number(3);
average = (n1 + n2 + n3)/3;
printf("The average is %0.2f\n",average);
}
double get_number(double num) {
double value = 0;
char c;
int i;
printf("Please input number %d: ", num);
while (c = getchar != '\n') {
if ( (c>9) || (c<0) ) {
printf("Incorrect character entered as a number - %c\n",c);
return(0);
}
else {
value = num;
}
}
return(value);
}
Original code
#include <stdio.h>
main () {
double n1,n2,n3;
double average;
printf("\nCompute the average of 3 integers\n");
printf("--------------------------------\n");
n1 = get_number(1);
n2 = get_number(2);
n3 = get_number(3);
average = (n1 + n2 + n3)/3;
printf("The average is %0.2f\n",average);
}
double get_number(int num) {
double value = 0;
char c;
printf("Please input number %d: ", num);
while (c = getchar() != '\n') {
if ( (c<=9) && (c>=0) ) {
printf("Incorrect character entered as a number - %c\n",c);
exit(-1);
}
else {
value = 10*value + c - '0';
}
}
return(value);
}
A few issues:
1. You should be using '9' and '0', since you want the ASCII values for digit '9' (0x39) and '0' (0x30), not 0x9 and 0x0.
if ( (c>'9') || (c<'0') ) {
2. != has higher precedence than =, so you need parens. Learn operator precedence, and if you're in doubt, use parens:
3. getchar is a function not a variable.
while ((c = getchar()) != '\n') {
4. You use the wrong conversion. num is a double, so you would need %f. Or, you could make num a int.
printf("Please input number %f: ", num);
5. You never actually use c in any way (except error checking). You always return 0 or num (see your else clause), which makes no sense. The else body of the original is correct.
You got the floating point parsing all wrong and shouldn't be doing it yourself. There's an easier way:
double get_number(double num) {
double value = 0.0;
printf("Please input number %lf: ", num);
scanf("%lf", &value);
return(value);
}
The issues with the original program are:
getchar() returns an ASCII code, and the condition was wrong. When checking for boundaries, use ((c<'0') || (c>'9')).
For the exit function you need to include "stdlib.h".
For the main function to understand what is get_number, you need to either move the function to be before the main function, or you can use a forward declaration.
The assignment operator (=) has lower precedence than the inequality operator (!=), so you need to use parenthesis, like: ((c = getchar()) != '\n')
You have actually created several more issues, so I wouldn't rely on your code.
In any case, in general - it is advised you study how to use a debugger. Once your code is compiling (and for that you'll need to get accustomed to the compilation error messages), you need to start debugging your code. I suggest you take some time to learn how to set breakpoints, set watches, and go step by step into your code. That skill is absolutely essential for a good developer.
Here's how I'd go about correcting the code ...
http://ideone.com/a0UMm -- compilation errors
http://ideone.com/ljUg1 -- warnings, but it works now
http://ideone.com/Qd0gp -- no errors, no warnings, test run ok
For 1. I used the "original code" as posted by you.
For 2. I used int main(void), declared the function get_number before defining main, added parenthesis in line 20, and added #include <stdlib.h>
For 3. I added return 0; before the final } of main. I also removed the extra output that messed up the ideone interface (it looks better on an interactive interface)
Edit more tests needed to complete the task of correcting the original code

Resources