I am aware of the low quality of the code, I am a beginner to programming in C.
The following program attemps to receive input from the user, turn it into tokens and then perform basic math with them. If the input exceeds 8 characters: ('256 256'), it fails to properly return a correct result, instead 256 256
is interpreted as `256 25.
It's been hours and hours of debugging and I cannot pinpoint the error.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define MAX 1024
typedef struct tokenReturn {
int arrayMembers;
char* tokens[];
}
t_return;
t_return *getAndTokenize(char* delim) {
// Get user input and store it as a string literal.
char* input = malloc(1024);
char lit_in[MAX];
if (fgets(input, MAX, stdin) == NULL) {
perror("Error: ");
exit(EXIT_FAILURE);
}
strncpy(lit_in, input, MAX);
free(input);
// Create the return structure to return not only the char* array but the max index as well.
t_return *return_struc = malloc(sizeof(t_return) MAX);
if (return_struc == NULL) {
puts("Allocation error");
perror("Error");
exit(EXIT_FAILURE);
}
// Assign first member due to the weird behaviour the strtok function has.
char *token = strtok(lit_in, delim);
return_struc->tokens[0] = token;
int i = 1; // We have to start at one since we already have one token stored in the array
while (true)
{
// Check to see if all the tokens have been obtained.
if((token = strtok(NULL, delim)) == NULL) {
break;
}
return_struc->tokens[i] = token;
i ;
}
// Assign i to arrayMembers so that we can determine array length.
return_struc->arrayMembers = i;
return return_struc;
}
float sum(float x, float y) {
return x y;
}
float multiply(float x, float y) {
return x * y;
}
float subs(float x, float y) {
return x - y;
}
float division(float x, float y) {
return x / y;
}
int main(void) {
// Init
printf("Operation: ");
t_return* tokens = getAndTokenize(" ");
float a = atof(tokens->tokens[0]);
char symbol = tokens->tokens[1][0];
float b = atof(tokens->tokens[2]);
float result;
// Check for the operation being done
switch (symbol) {
case ' ':
result = sum( a, b );
break;
case '-':
result = subs(a, b);
break;
case '/':
result = division( a, b );
break;
case '*':
result = multiply( a, b );
break;
default:
puts("Operation not recognized!");
exit(EXIT_FAILURE);
}
printf("Result is: %.3lf\n", result);
exit(EXIT_SUCCESS);
}
CodePudding user response:
getAndTokenize
copies the input into lit_in
, which is an automatic object inside getAndTokenize
. Once getAndTokenize
returns, the memory for lit_in
is no longer reserved, and the pointers you put into the t_return
structure pointing into lit_in
are no longer valid. Some of the other code in main
does things that reuse that memory for other purposes. Change getAndTokenize
to keep the input in an allocated buffer that is not freed until the program is done using the data in it.