I’m trying to solve some exercises in preparation for an incoming test and i’ve encountered a problem that i’ve fixed by chance and i’d like to understand what’s going on with my code.
The exercise requires me to create a struct type that represent a monomial of 4 variables (x, y, w and z) and two functions, print_term that will show the monomial on screen and read_term, that take an user input and returns a monomial. The exercise requires the user input to be of the form “C V P V P V P V P .”, where C is the coefficient of the monomial, V is one of the 4 variables (in any order) and P is their power.
//Here is the monomial struct
struct term{
int coef;
int potx;
int poty;
int potw;
int potz;
};
My problem lies in the read_term function: sometimes, if C is negative the power of one of the variables will be set to -48 (which definitely come from my attempt to convert the char that represent a digit to it’s value in int): for example, the input “-257 x 2 z 3 w 1 .” will return me -257(x^2)(w^-48)(z^3), while “257 x 2 z 3 w 1 .” will instead return the correct result 275(x^2)w(z^3).
struct term read_term(){
struct term result;
result.coef =0;
result.potx =0;
result.poty =0;
result.potw =0;
result.potz =0;
char input[255];
for(int i =0; i < sizeof(input)/sizeof(input[0]);i ){
input[i] = '\0';
}
char inputNeg[255];
int negativo = 0;
printf("Termine: \n");
fgets(input, 255, stdin);
input[strlen(input)-1] = '\0'; //should remove '\n'
//I remeve the minus sign, i'll add it back in later.
if(input[0] == '-'){
negativo = 1;
int i = 1;
do{
inputNeg[i-1] = input[i];
i ;
}while(input[i] != '\0');
printf("\n%s\n", input);
strcpy(input, inputNeg);
printf("\n%s\n", input);
}
////////////THIS MAKE OR BRAKE THE CODE
//printf("\ninput prova\n");
for(int i =0; i < sizeof(input)/sizeof(input[0]);i ){
//printf("%c", input[i]);
}
////////////////////////////
//Change struct term result based on input:
int index = 0;
int cifreCof[12];
for(int j=0; j< sizeof(cifreCof)/sizeof(cifreCof[0]);j ){
cifreCof[j] = 0;
}
int temp = 0;
int pot = 0;
do{
//Coeff is always at index 0
if(index == 0){
//Conversion from char to int
do{
cifreCof[index] = input[index] - '0';
index ;
pot ;
}while(input[index] != ' ');
//Puts all the digits in one int
for(int i=0; i < sizeof(cifreCof)/sizeof(cifreCof[0]); i ){
temp = temp (cifreCof[i]*pow(10, pot-1));
pot--;
}
//Place the minus sign back.
if(negativo == 0){
result.coef = temp;
}
else{
result.coef = (-1)*temp;
}
}
// Variabili.
else{
//White space
if(input[index] == ' '){
index ;
}
//x char
else if(input[index] == 'x'){
index ;
index ;
//per ora mi limito ad esponenti a una cifra
if(input[index] != '.'){
result.potx = input[index] - '0';
index ;
}
else{index ;}
}
//y char
else if(input[index] == 'y'){
index ;
index ;
//per ora mi limito ad esponenti a una cifra
if(input[index] != '.'){
result.poty = input[index] - '0';
index ;
}
else{index ;}
}
// w char
else if(input[index] == 'w'){
index ;
index ;
//per ora mi limito ad esponenti a una cifra
if(input[index] != '.'){
result.potw = input[index] - '0';
index ;
}
else{index ;}
}
//z char
else if(input[index] == 'z'){
index ;
index ;
//per ora mi limito ad esponenti a una cifra
if(input[index] != '.'){
result.potz = input[index] - '0';
index ;
}
else{index ;}
}
else{index ;}
}
}while(input[index] != '\0');
return result;
}
In an attempt to identify the problem, i placed a for loop to print the array i use to save the input, just to discover that this loop changed the outcome of the function to the correct result: i decided to keep the loop but emptying it of its code, and still the result is correct. I have no idea how it fix my code but it does. Any explanation?
CodePudding user response:
It is very unlikely the empty loop had anything to do with fixing your code. But undefined behavior may have played a role in exposing the problem.
When a variable is created, the contents of memory allocated is unknown. Therefore, if it is used before being initialized, the results will be unpredictable.
A simple initialization will work:
char inputNeg[255] = {0};//initializes all elements of array in one step.
Although the for loop does initialize the array here
char input[255];
for(int i =0; i < sizeof(input)/sizeof(input[0]);i ){
input[i] = '\0';
}
...initialization during declaration is more efficient:
char input[255] = {0};
Do the same for cifreCof
Regarding removing the newline after calling fgets
, consider using this method:
//input[strlen(input)-1] = '\0';//unsafe for an empty string
input[strcspn(input, "\n")] = 0;//this is safe, and will remove newline