How to distinguish new line from EOF while reading from file - c

I am trying to build a program that could add up binary numbers, of arbitrary length, separated by a whitespace. I don't want to be limited by a maximum number length, therefore I'm doing everything without built-in number types, only chars. I read the numbers from a file. I perform everything on stack.
I can't loop the part where I read and add numbers. My guess is that it's because I can't find a way to distinguish new line from EOF. The program works this way: I read first number and save it into first stack, then I read second number and save in second stack. Then I add it up, save into third stack and transfer it to first stack. I read next number, save it into second stack, add up and so on. So I basically want to loop the second reading and summing. Here is the source code part:
while( !isspace(c=(char)getc(ifp))) {
if( c == '0' || c == '1'){
if(!push(&a , c)){
clearStack(&a);
printf("alloc error");
return 0;
}
}else{
clearStack(&a);
printf("error1");
return 0;
}
}
if( a.size == 0 ){
printf("error2");
return 0;
}
while (!feof(ifp)) {
while( !isspace(c=(char)getc(ifp))) {
if( c == '0' || c == '1'){
if(!push(&b , c)){
clearStack(&a);
clearStack(&b);
printf("alloc error");
return 0;
}
}
else{
//clearStack(&a);
//clearStack(&b);
printf("error3");
//return 0;
}
}
if( b.size == 0 ){
if (a.size == 0){
printf("error4");
}
}
topA = a.size;
topB = b.size;
carry = 0;
while( topA > 0 || topB > 0) {
if ( ( topA > 0 ) ){
topA--;
if(a.data[topA] == '1'){
x = 1;
}else{
x = 0;
}
}else{
x = 0;
}
if ( ( topB > 0 ) ){
topB--;
if(b.data[topB] == '1'){
y = 1;
}else{
y = 0;
}
}else{
y = 0;
}
sum = x + y + carry;
if (sum == 2 || sum == 3){
carry = 1;
}else{
carry = 0;
}
if (sum == 1 || sum == 3) {
c = '1';
}else{
c = '0';
}
if(!push(&output , c)){
clearStack(&a);
clearStack(&b);
clearStack(&output);
printf("alloc error");
return 0;
}
}
if (carry == 1) {
if(!push(&output , '1')){
clearStack(&a);
clearStack(&b);
clearStack(&output);
printf("alloc error");
return 0;
}
}
clearStack(&a);
for (i=0; i < output.size; i++){
push(&a , output.data[i]);
}
clearStack(&b);
clearStack(&output);
} /*end of EOF while*/
For some reason, although it reads multiple times, it reads wrong and works only for 2 numbers. The file looks like this: "1 1", but when its "1 1 1" it will just add first 2 numbers. I don't know where am I making a mistake. Below I attach the whole source code. I invoke the program in console like this: ./program file. I know that the case is poorly described but can't do it in a better manner, I will add comments if anything is needed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct stack {
char *data;
int size;
};
int push(struct stack * s, char c){
char * newData = (char *)realloc( s->data , (s->size + 1) * sizeof(char));
if( newData ){
s->data = newData;
s->data[s->size]=c;
s->size++;
return 1;
}else{
return 0;
}
}
/* not needed */
char pop(struct stack * s){
if(s->size > 0){
char result = s->data[s->size-1];
char * newData = (char *)realloc( s->data , s->size - 1);
if( newData ){
s->data = newData;
s->size--;
return result;
}else{
return 0;
}
}
else{
return 0;
}
}
struct stack newStack(){
struct stack s;
s.data = NULL;
s.size = 0;
return s;
}
void clearStack(struct stack * s){
free(s->data);
s->data = NULL;
s->size = 0;
}
int main (int argc, char const * argv[])
{
struct stack a = newStack();
struct stack b = newStack();
int topA, topB, x , y, carry, sum,i , start;
struct stack output = newStack();
char c;
FILE *ifp;
if(argc!=2){printf("Usage: ./a.out input_file."); return(1);}
if(!(ifp = fopen(argv[1], "r"))){printf("Unable to open input file!"); return(2);}
while( !isspace(c=(char)getc(ifp))) {
if( c == '0' || c == '1'){
if(!push(&a , c)){
clearStack(&a);
printf("alloc error");
return 0;
}
}else{
clearStack(&a);
printf("error1");
return 0;
}
}
if( a.size == 0 ){
printf("error2");
return 0;
}
while (!feof(ifp)) {
while( !isspace(c=(char)getc(ifp))) {
if( c == '0' || c == '1'){
if(!push(&b , c)){
clearStack(&a);
clearStack(&b);
printf("alloc error");
return 0;
}
}
else if (c == '\0' || c == ' ' || c == '\n'){
}
else{
//clearStack(&a);
//clearStack(&b);
printf("error3");
//return 0;
}
}
if( b.size == 0 ){
if (a.size == 0){
printf("error4");
//return 0;
}
}
topA = a.size;
topB = b.size;
carry = 0;
while( topA > 0 || topB > 0) {
if ( ( topA > 0 ) ){
topA--;
if(a.data[topA] == '1'){
x = 1;
}else{
x = 0;
}
}else{
x = 0;
}
if ( ( topB > 0 ) ){
topB--;
if(b.data[topB] == '1'){
y = 1;
}else{
y = 0;
}
}else{
y = 0;
}
sum = x + y + carry;
if (sum == 2 || sum == 3){
carry = 1;
}else{
carry = 0;
}
if (sum == 1 || sum == 3) {
c = '1';
}else{
c = '0';
}
if(!push(&output , c)){
clearStack(&a);
clearStack(&b);
clearStack(&output);
printf("alloc error");
return 0;
}
}
if (carry == 1) {
if(!push(&output , '1')){
clearStack(&a);
clearStack(&b);
clearStack(&output);
printf("alloc error");
return 0;
}
}
clearStack(&a);
for (i=0; i < output.size; i++){
push(&a , output.data[i]);
}
clearStack(&b);
clearStack(&output);
} /*end of EOF while*/
for (i=a.size - 1; i >= 0; i--){
if(a.data[i] == '1' || start){
start=1;
printf("%c", a.data[i]);
}
}
printf("\n");
clearStack(&a);
//clearStack(&b);
//clearStack(&output);
return 0;
}

Related

My program has AddressSanitizer error but I'm not sure how to read it

I'm relatively new to C and just finished a train station schedule program that looks for the nearest time departing time, from a schedule file, relative to the user input time, source, and destination. The restrictions were no string.h and no dynamic memory allocation of any kind. The program worked fine when I tested it but when marked, it produced AddressSanitizer errors which we haven't learned yet. I'm not sure how to read the error code.
The Following is my code:
#include <stdio.h>
#include <stdlib.h>
#define lineSize 4096
int main(int argc, char* argv[]) {
if(argc != 4){
printf("Please provide <source> <destination> <time> as command line arguments\n");
return(0);
}
int c = 0;
while(argv[3][c] != 0){
c++;
}
if(c < 8){
printf("Please enter a proper time\n");
return(0);
}
char line[lineSize];
FILE * fpointer = fopen("timetable.list", "r");
int i;
int j;
int StartSize;
int DestinationSize;
int DepartTime;
for(StartSize = 0; argv[1][StartSize] != '\0'; StartSize += 1){
continue;
}
for(DestinationSize = 0; argv[2][DestinationSize] != '\0'; DestinationSize += 1){
continue;
}
for(DepartTime = 0; argv[3][DepartTime] != '\0'; DepartTime += 1){
continue;
}
int hour = 23;
int min = 59;
int sec = 59;
int check = 1;
int matchStart = 0;
int matchEnd = 0;
int checkNearestTime = 0;
int isThereATime = 0;
while(fgets(line, lineSize, fpointer) != NULL){
check = 1;
for(i = 0; i < StartSize; i++){
if(argv[1][i] == line[i]){
matchStart = 1;
continue;
}
else{
check = 0;
matchStart = 0;
}
}
if(check == 1){
i = 0;
int j = StartSize + 2;
while(i < DestinationSize){
if(argv[2][i] == line[j]){
i += 1;
j += 1;
matchEnd = 1;
}
else{
check = 0;
matchEnd = 0;
break;
}
}
}
if(check == 1){
i = 0;
j = StartSize + DestinationSize + 4;
while(i < DepartTime){
if(argv[3][i] == line[j]){
i += 1;
j += 1;
}
else{
check = 0;
break;
}
}
if(check == 1){
printf("The next train to %s from %s departs at %s\n", argv[2], argv[1], argv[3]);
return 0;
}
if(check == 0){
j = StartSize + DestinationSize + 4;
int lineFullHour = (line[j] - '0') * 10 + (line[j+1] -'0');
int lineFullMin = (line[j+3] - '0') * 10 + (line[j+4] -'0');
int lineFullSec = (line[j+6] - '0') * 10 + (line[j+7] -'0');
int argvHour = (argv[3][0] - '0') * 10 + (argv[3][1]-'0');
int argvMin = (argv[3][3] - '0') * 10 + (argv[3][4] -'0');
int argvSec = (argv[3][6] - '0') * 10 + (argv[3][7] -'0');
if(lineFullHour > argvHour){
if(lineFullHour < hour){
hour = lineFullHour;
min = lineFullMin;
sec = lineFullSec;
checkNearestTime = 1;
}
else if(lineFullHour == hour){
if(lineFullMin < min){
min = lineFullMin;
sec = lineFullSec;
checkNearestTime = 1;
}
else if(lineFullMin == min){
if(lineFullSec < sec){
sec = lineFullSec;
checkNearestTime = 1;
}
}
}
}
else if(lineFullHour == argvHour && lineFullMin > argvMin){
if(lineFullHour < hour){
hour = lineFullHour;
min = lineFullMin;
sec = lineFullSec;
checkNearestTime = 1;
}
else if(lineFullHour == hour){
if(lineFullMin < min){
min = lineFullMin;
sec = lineFullSec;
checkNearestTime = 1;
}
else if(lineFullMin == min){
if(lineFullSec < sec){
sec = lineFullSec;
checkNearestTime = 1;
}
}
}
}
else if(lineFullHour == argvHour && lineFullMin == argvMin && lineFullSec > argvSec){
if(lineFullHour < hour){
hour = lineFullHour;
min = lineFullMin;
sec = lineFullSec;
checkNearestTime = 1;
}
else if(lineFullHour == hour){
if(lineFullMin < min){
min = lineFullMin;
sec = lineFullSec;
checkNearestTime = 1;
}
else if(lineFullMin == min){
if(lineFullSec < sec){
sec = lineFullSec;
checkNearestTime = 1;
}
}
}
}
}
}
if(matchStart == 1 && matchEnd == 1 && checkNearestTime == 1){
isThereATime = 1;
}
}
if(isThereATime == 1){
printf("The next train to %s from %s departs at %02d:%02d:%02d\n", argv[2], argv[1], hour, min, sec);
return 0;
}
if(isThereATime == 0){
printf("No suitable trains can be found\n");
return 0;
}
return 0;
}
The source code (line 53) and your report do not match (line 59) do not match. It complains about a NULL pointer, per #kaylum, that only happens if fpointer is NULL. In turn this means │FILE * fpointer = fopen("timetable.list", "r"); failed. Always implement error checking:
#include <errno.h>
#include <string.h>
...
FILE * fpointer = fopen("timetable.list", "r");
if(!fpointer) {
fprintf(stderr, "fopen failed with %s", strerror(errno)));
exit(1);
}

Issues with memcheck in C calculator

I'm writing a Calculator in C from scratch (homework assignment) and have troubles with memory somewhere.. The algorithm works perfectly, but I'm getting a set of Valgrind errors/warnings, e.g.:
echo -n "1" | valgrind ./a.out --track-origins=yes
==14261== Conditional jump or move depends on uninitialised value(s)
==14261== at 0x400B9F: create_rpn (main.c:53)
==14261== by 0x400742: main (main.c:253)
My makefile:
all:
gcc main.c -g -O2 -Wall -Werror -std=c99
My source code is below (and on GitHub). Can you help with it? Thank you in advance!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 1024
// needs to check priority
int get_power(char op) {
if (op == '+') {
return 2;
} else if (op == '-') {
return 2;
} else if (op == '*') {
return 4;
} else if (op == '/') {
return 4;
} else {
return 0;
}
}
// checks if current char is operator
int is_operator(char op) {
if (op == '+' || op == '-' || op == '*' || op == '/') {
return 1;
} else {
return 0;
}
}
// checks if current char is digit
int is_digit(char op) {
if ((op >= '0' && op <= '9') || op == '.') {
return 1;
} else {
return 0;
}
}
// evaulates array in Postfix
double evaulate_rpn(char** exp, size_t len) {
double* stack = (double* ) malloc(len*sizeof(double)); // stack for operands
double a1 = 0.0;
double a2 = 0.0; // buffers to save stack items
size_t place = 0; // current stack size
for (size_t i = 0; i < len; ++i) {
if (is_operator(*exp[i]) == 1) {
// takes out last 2 operands, processes
if (place > 1) {
a1 = stack[place - 2];
a2 = stack[place - 1];
if (strncmp(exp[i], "+", 1) == 0) {
stack[place - 2] = a1 + a2;
} else if (strncmp(exp[i], "-", 1) == 0) {
stack[place - 2] = a1 - a2;
} else if (strncmp(exp[i], "*", 1) == 0) {
stack[place - 2] = a1 * a2;
} else if (strncmp(exp[i], "/", 1) == 0) {
stack[place - 2] = a1 / a2;
}
place -= 1;
} else if (place == 1) {
// unary minus, unary plus..
a1 = stack[place - 1];
if (strncmp(exp[i], "-", 1) == 0) {
stack[place - 1] = 0 - a1;
} else if (strncmp(exp[i], "+", 1) == 0) {
stack[place - 1] = a1;
}
} else {
// wrong order / anything else
printf("[error]");
exit(0);
}
} else {
// is operand -> convert char to double -> save double to stack
stack[place] = atof(exp[i]);
place++ ;
}
}
float res = stack[0];
free(stack);
return res; // result here
}
void push_to_stack(char*** reverse, size_t* inited_lines, size_t* used_lines, char* item, size_t size) {
if(*inited_lines <= *used_lines){
*inited_lines *= 2;
char** buf = (char** ) realloc(*reverse, (*inited_lines)*sizeof(char** ));
if (buf) {
*reverse = buf;
} else {
printf("[error]");
exit(0);
}
}
char* str = calloc(size + 1, sizeof(char));
if (str) {
memcpy(str, item, size + 1);
str[size] = '\0';
(*reverse)[*used_lines] = str;
(*used_lines)++ ;
} else {
printf("[error]");
exit(0);
}
}
// transform from Infix to Postfix notation
double create_rpn(char* exp, size_t len){
// stack of chars for operands ()+-*/
char* stack = (char* ) malloc(len);
if (stack == NULL) {
printf("[error]");
exit(0);
}
size_t stack_top = 0; // position of last item in stack
// array of numbers
size_t inited_lines = 1;
size_t used_lines = 0;
char** reverse = (char** ) malloc(inited_lines*sizeof(char* ));
if (reverse == NULL) {
printf("[error]");
exit(0);
}
char buffer = 0;
int bracket_deep = 0;
int digit = 0; // flag to start parsing Numbers/digits
size_t start_index = 0; // for parsing Long-Vals
size_t index = 0;
while (index <= len) {
buffer = exp[index]; // buffer constats only 1 char but it is a string
if (is_digit(buffer) == 1) {
// save first digit place
if (digit == 0) {
start_index = index;
digit = 1;
}
} else {
// push to stack when Num is over
if (digit == 1) {
digit = 0;
size_t size = index - start_index; // size of str
push_to_stack(&reverse, &inited_lines, &used_lines, exp + start_index, size);
}
// push Operands + check priority
if (is_operator(buffer) == 1) {
size_t power = get_power(buffer);
for (int i = stack_top - 1; i >= 0; --i) {
if (stack[i] == '(') {
break;
}
if (get_power(stack[i]) >= power) {
push_to_stack(&reverse, &inited_lines, &used_lines, &stack[i], 1);
stack_top-- ;
}
}
// push current Operand to stack
stack[stack_top++ ] = buffer;
} else if (buffer == '(') {
stack[stack_top++ ] = buffer;
bracket_deep++ ;
} else if (buffer == ')') {
// push operands to result
bracket_deep-- ;
stack_top-- ; // if no, '' will be added to output
while (stack[stack_top] != '(') {
push_to_stack(&reverse, &inited_lines, &used_lines, &stack[stack_top], 1);
if (stack_top > 0) {
stack_top-- ;
} else {
break;
}
}
} else if (buffer == ' ' || buffer == '\n') {
// ignore this case
} else if (buffer == '\0') {
for (int i = stack_top - 1; i >= 0; --i) {
push_to_stack(&reverse, &inited_lines, &used_lines, &stack[i], 1);
}
stack_top = 0;
} else {
printf("[error]"); // - wrong char: '%s', %c\n", buffer, *buffer); // wrong char!
exit(0);
}
}
if (bracket_deep < 0) {
printf("[error]"); // wrong bracket expr
exit(0);
}
index++ ;
}
free(stack);
if (bracket_deep == 0) {
double res = evaulate_rpn(reverse, used_lines);
for (int i = 0; i < inited_lines; i++) {
free(reverse[i]);
}
free(reverse);
return res;
} else {
printf("[error]"); // wrong brackets
exit(0);
}
}
int main() {
char* expression = (char* ) malloc(MAX_LEN*sizeof(char));
if (expression) {
size_t len = 0;
while (scanf("%c", &expression[len]) != -1) { // switch to getch ???
if (expression[len] != ' ') { // save everything except spaces
len++ ;
}
}
double result = create_rpn(expression, len);
printf("%.2f", result);
free(expression);
} else {
printf("[error]");
exit(0);
}
return 0;
}
You are reading 1 byte beyond the array bound, because your while loop in create_rpn() is
while (index <= len)
but should be
while (index < len)
/* ^ without the = */
since arrays are 0 indexed, exp[len] is beyond the array.
Also
Avoid redundant parentheses, they make the code ugly and hence, hard to read and understand.
Do not cast the return value of malloc(), read the link and you will understand why.
Another tip to make your code clearer, is to avoid mixing code with declarations, for a compiler it's easy to see a variable's scope, but not for the eyes.

Printing string pointers in c

So, essentially I have two files:
File 1:
//
// main.c
// frederickterry
//
// Created by Rick Terry on 1/15/15.
// Copyright (c) 2015 Rick Terry. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int size (char *g) {
int ofs = 0;
while (*(g+ofs) != '\0') {
++ofs;
}
return ofs;
}
int parse(char *g) {
// Setup
char binaryConnective;
int negated = 0;
// Looking for propositions
int fmlaLength = size(g);
if(fmlaLength == 0) {
return 1;
}
if(fmlaLength == 1) {
if(g[0] == 'p') {
return 1;
} else if (g[0] == 'q') {
return 1;
} else if (g[0] == 'r') {
return 1;
} else {
return 0;
}
}
// Now looking for negated preposition
if(fmlaLength == 2) {
char temp[100];
strcpy(temp, g);
if(g[0] == '-') {
negated = 1;
int negatedprop = parse(g+1);
if(negatedprop == 1) {
return 2;
}
}
}
// Checking if Binary Formula
char arrayleft[50];
char arrayright[50];
char *left = "";
char *right = "";
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int binarypresent = 0;
if(fmlaLength != 1 && fmlaLength != 2) {
if(g[0] == '-') {
int negatedBinary = parse(g+1);
if(negatedBinary == 1 || negatedBinary == 2 || negatedBinary == 3) {
return 2;
} else {
return 0;
}
}
int i = 0;
int l = 0;
int p = strlen(g);
for(l = 0; l < strlen(g)/2; l++) {
if(g[l] == '(' && g[p-l-1] == ')') {
i++;
}
}
for(int q = i; q < strlen(g); q++) {
if(g[q] == '(') {
numLeft++;
} else if(g[q] == ')') {
numRight++;
}
arrayleft[q] = g[q];
//printf("%c", arrayleft[i]);
//printf("%s", left);
if((numRight == numLeft) && (g[q+1] == 'v' || g[q+1] == '>' || g[q+1] == '^')) {
arrayleft[q+1] = '\0';
bclocation = q+1;
binaryConnective = g[q+1];
binarypresent = 1;
// printf("The binary connecive is: %c\n", binaryConnective);
break;
}
}
if(binarypresent == 0) {
return 0;
}
int j = 0;
for(int i = bclocation+1; i < strlen(g)-1; i++) {
arrayright[j] = g[i];
j++;
}
arrayright[j] = '\0';
left = &arrayleft[1];
right = &arrayright[0];
//printf("Printed a second time, fmla 1 is: %s", left);
int parseleft = parse(left);
// printf("Parse left result: %d\n", parseleft);
if(parseleft == 0) {
return 0;
}
int parseright = parse(right);
if(parseright == 0) {
return 0;
}
// printf("Parse right result: %d\n", parseleft);
if(negated == 1) {
return 2;
} else {
return 3;
}
}
return 0;
}
int type(char *g) {
if(parse(g) == 1 ||parse(g) == 2 || parse(g) == 3) {
if(parse(g) == 1) {
return 1;
}
/* Literals, Positive and Negative */
if(parse(g) == 2 && size(g) == 2) {
return 1;
}
/* Double Negations */
if(g[0] == '-' && g[1] == '-') {
return 4;
}
/* Alpha & Beta Formulas */
char binaryConnective;
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int binarypresent = 0;
int i = 0;
if(g[0] == '(') {
i++;
}
if(g[0] == '-') {
i++;
if(g[1] == '(') {
i++;
}
}
for(i; i < strlen(g); ++i) {
if(g[i] == '(') {
numLeft++;
} else if(g[i] == ')') {
numRight++;
}
if(numRight == numLeft) {
if(g[i+1] == 'v' || g[i+1] == '>' || g[i+1] == '^') {
bclocation = i+1;
binaryConnective = g[i+1];
binarypresent = 1;
break;
}
}
}
/* Connective established */
if(binaryConnective == '^') {
if(g[0] == '-') {
return 3;
} else {
return 2;
}
} else if(binaryConnective == '>') {
if(g[0] == '-') {
return 2;
} else {
return 3;
}
} else if (binaryConnective == 'v') {
if(g[0] == '-') {
return 2;
} else {
return 3;
}
}
}
return 0;
}
char bin(char *g) {
char binaryConnective;
char arrayLeft[50];
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int i = 0;
if(g[0] == '(') {
i++;
}
if(g[0] == '-') {
i++;
if(g[1] == '(') {
i++;
}
}
for(i; i < strlen(g); ++i) {
if(g[i] == '(') {
numLeft++;
} else if(g[i] == ')') {
numRight++;
}
int j = 0;
arrayLeft[j++] = g[i];
if(numRight == numLeft) {
if(g[i+1] == 'v' || g[i+1] == '>' || g[i+1] == '^') {
arrayLeft[i+1] = '\0';
bclocation = i+1;
binaryConnective = g[i+1];
return binaryConnective;
}
}
}
return binaryConnective;
}
char *partone(char *g) {
char binaryConnective;
char arrayLeft[50];
char arrayRight[50];
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int i = 0;
if(g[0] == '(') {
i++;
}
if(g[0] == '-') {
i++;
if(g[1] == '(') {
i++;
}
}
int j = 0;
for(i; i < strlen(g); ++i) {
if(g[i] == '(') {
numLeft++;
} else if(g[i] == ')') {
numRight++;
}
arrayLeft[j] = g[i];
if(numRight == numLeft) {
if(g[i+1] == 'v' || g[i+1] == '>' || g[i+1] == '^') {
arrayLeft[j+1] = '\0';
bclocation = i+1;
binaryConnective = g[i+1];
break;
}
}
j++;
}
int m = 0;
for(int k = bclocation+1; k < strlen(g)-1; k++) {
arrayRight[m] = g[k];
m++;
}
arrayRight[m] = '\0';
char* leftSide = &arrayLeft[0];
// printf("%s\n", leftSide);
// printf("%s\n", rightSide);
int k = 0;
k++;
return leftSide;
}
char *parttwo(char *g) {
char binaryConnective;
char arrayLeft[50];
char arrayRight[50];
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int i = 0;
if(g[0] == '(') {
i++;
}
if(g[0] == '-') {
i++;
if(g[1] == '(') {
i++;
}
}
int j = 0;
for(i; i < strlen(g); ++i) {
if(g[i] == '(') {
numLeft++;
} else if(g[i] == ')') {
numRight++;
}
arrayLeft[j] = g[i];
if(numRight == numLeft) {
if(g[i+1] == 'v' || g[i+1] == '>' || g[i+1] == '^') {
arrayLeft[j+1] = '\0';
bclocation = i+1;
binaryConnective = g[i+1];
break;
}
}
j++;
}
int m = 0;
int n = size(g) - 1;
if(g[strlen(g)-1] != ')') {
n++;
}
for(int k = bclocation+1; k < n; k++) {
arrayRight[m] = g[k];
m++;
}
arrayRight[m] = '\0';
char* leftSide = &arrayLeft[0];
char* rightSide = &arrayRight[0];
// printf("%s\n", leftSide);
// printf("%s\n", rightSide);
return rightSide;
}
char *firstexp(char *g) {
char* left = partone(g);
char leftArray[50];
int i = 0;
for(i; i < strlen(left); i++) {
leftArray[i] = left[i];
}
leftArray[i] = '\0';
char binConnective = bin(g);
int typeG = type(g);
if(typeG == 2) {
if(binConnective == '^') {
return &leftArray;
} else if(binConnective == '>') {
return &leftArray;
}
} else if(typeG == 3) {
if(binConnective == 'v')
return &leftArray;
}
char temp[50];
for(int i = 0; i < strlen(leftArray); i++) {
temp[i+1] = leftArray[i];
}
temp[0] = '-';
char* lefttwo = &temp[0];
if(typeG == 2) {
if(binConnective == 'v') {
return lefttwo;
}
} else if(typeG == 3) {
if(binConnective == '>' || binConnective == '^') {
return lefttwo;
}
}
return "Hello";
}
char *secondexp(char *g) {
// char binaryConnective = bin(g);
// char* right = parttwo(g);
// char rightArray[50];
// int i = 0;
// for(i; i< strlen(right); i++) {
// rightArray[i+1] = right[i];
// }
// rightArray[i] = '\0';
// int typeG = type(g);
// if(type(g) == 2) {
// if(binaryConnective == '^') {
// return &rightArray;
// }
// } else if(type(g) == 3) {
// if(binaryConnective == 'v' || binaryConnective == '>') {
// return &rightArray;
// }
// }
return "Hello";
}
typedef struct tableau tableau;
\
\
struct tableau {
char *root;
tableau *left;
tableau *right;
tableau *parent;
int closedbranch;
};
int closed(tableau *t) {
return 0;
}
void complete(tableau *t) {
}
/*int main(int argc, const char * argv[])
{
printf("Hello, World!\n");
printf("%d \n", parse("p^q"));
printf("%d \n", type("p^q"));
printf("%c \n", bin("p^q"));
printf("%s\n", partone("p^q"));
printf("%s\n", parttwo("p^q"));
printf("%s\n", firstexp("p^q"));
printf("Simulation complete");
return 0;
}*/
File 2:
#include <stdio.h>
#include <string.h> /* for all the new-fangled string functions */
#include <stdlib.h> /* malloc, free, rand */
#include "yourfile.h"
int Fsize = 50;
int main()
{ /*input a string and check if its a propositional formula */
char *name = malloc(Fsize);
printf("Enter a formula:");
scanf("%s", name);
int p=parse(name);
switch(p)
{case(0): printf("not a formula");break;
case(1): printf("a proposition");break;
case(2): printf("a negated formula");break;
case(3): printf("a binary formula");break;
default: printf("what the f***!");
}
printf("\n");
if (p==3)
{
printf("the first part is %s and the second part is %s", partone(name), parttwo(name));
printf(" the binary connective is %c \n", bin(name));
}
int t =type(name);
switch(t)
{case(0):printf("I told you, not a formula");break;
case(1): printf("A literal");break;
case(2): printf("An alpha formula, ");break;
case(3): printf("A beta formula, ");break;
case(4): printf("Double negation");break;
default: printf("SOmewthing's wrong");
}
if(t==2) printf("first expansion fmla is %s, second expansion fmla is %s\n", firstexp(name), secondexp(name));
if(t==3) printf("first expansion fmla is %s, second expansion fmla is %s\n", firstexp(name), secondexp(name));
tableau tab;
tab.root = name;
tab.left=0;
tab.parent=0;
tab.right=0;
tab.closedbranch=0;
complete(&tab);/*expand the root node then recursively expand any child nodes */
if (closed(&tab)) printf("%s is not satisfiable", name);
else printf("%s is satisfiable", name);
return(0);
}
If you look at the first file, you'll see a method called * firstexp(char * g).
This method runs perfectly, but only if another method called * secondexp(char * g) is commented out.
If * secondexp(char * g) is commented out, then *firstexp runs like this:
Enter a formula:((pvq)>-p)
a binary formula
the first part is (pvq) and the second part is -p the binary connective is >
A beta formula, first expansion fmla is -(pvq), second expansion fmla is Hello
((pvq)>-p) is satisfiableProgram ended with exit code: 0
otherwise, if *secondexp is not commented out, it runs like this:
Enter a formula:((pvq)>-p)
a binary formula
the first part is (pvq) and the second part is -p the binary connective is >
A beta formula, first expansion fmla is \240L, second expansion fmla is (-
((pvq)>-p) is satisfiable. Program ended with exit code: 0
As you can see, the outputs are completely different despite the same input. Can someone explain what's going on here?
In the commented-out parts of secondexp and in parttwo, you return the address of a local variable, which you shouldn't do.
You seem to fill a lot of ad-hoc sized auxiliary arrays. These have the problem that they might overflow for larger expressions and also that you cannot return them unless you allocate them on the heap with malloc, which also means that you have to free them later.
At first glance, the strings you want to return are substrings or slices of the expression string. That means that the data for these strings is already there.
You could (safely) return pointers into that string. That is what, for example strchr and strstr do. If you are willing to modify the original string, you could also place null terminators '\0' after substrings. That's what strtok does, and it has the disadvantage that you lose the information at that place: If you string is a*b and you modify it to a\0b, you will not know which operator there was.
Another method is to create a struct that stores a slice as pointer into the string and a length:
struct slice {
const char *p;
int length;
};
You can then safely return slices of the original string without needing to worry about additional memory.
You can also use the standard functions in most cases, if you stick to the strn variants. When you print a slice, you can do so by specifying a field width in printf formats:
printf("Second part: '%.*s'\n", s->length, s->p);
In your parttwo() function you return the address of a local variable
return rightSide;
where rightSide is a pointer to a local variable.
It appears that your compiler gave you a warning about this which you solved by making a pointer to the local variabe arrayRight, that may confuse the compiler but the result will be the same, the data in arrayRight will no longer exist after the function returns.
You are doing the same all over your code, and even worse, in the secondexp() function you return a the address of a local variable taking it's address, you are not only returning the address to a local variabel, but also with a type that is not compatible with the return type of the function.
This is one of many probable issues that your code may have, but you need to start fixing that to continue with other possible problems.
Note: enable extra warnings when compiler and listen to them, don't try to fool the compiler unless you know exactly what you're doing.

lexicographical comparison of the two blocks

which performs a lexicographical comparison of the two blocks. I test my
program using various types of blocks.
The tests for characters are all goods.
The First test isn't Ok because the good answer is 0 but now is 1.
The second test is ok (1 == 1)
The third test is ok (-1 == -1)
Help me for the first test.
Thanks
This is my codes :
int compare_ints(const void* v1, const void* v2) {
int *a = (int*)v1;
int *b = (int*)v2;
if (*a == *b) return 0;
else if (*a > *b) return 1;
else return -1;
}
int compare_gen(const void *block1, const void *block2,
size_t elem_size, size_t block1size, size_t block2size,
int (*compare_it)(const void*, const void*)) {
int i = 0;
int result = -2;
if ( elem_size == sizeof(char) )
{
while ( i < block1size && i < block2size)
{
result = (*compare_it)((&((char*)block1)[i]),(&((char*)block2)[i]));
if ( result == 0)
{
i++;
}
else if ( result == -1 || result == 1 )
{
return result;
}
}
if ( result == 0 )
{
if (i == block1size && i == block2size)
{
return result;
}
else if (i != block1size && i == block2size)
{
result = -1;
return result;
}
else
{
result = 1;
return result;
}
}
}
else if (elem_size == sizeof(int))
{
while ( i < block1size && i < block2size)
{
result = (*compare_it)((&((int*)block1)[i]),(&((int*)block2)[i]));
if ( result == 0)
{
i++;
}
else if ( result == -1 || result == 1 )
{
return result;
}
}
if ( result == 0 )
{
if (i == block1size && i == block2size)
{
return result;
}
else if (i != block1size && i == block2size)
{
result = -1;
return result;
}
else
{
result = 1;
return result;
}
}
}
return result;
}
int main()
{
int array1 [10] = {10};
int array2 [10] = {10};
int array3 [10] = {10};
int array4 [9] = {10};
int i;
for (i = 0; i < 10; i++) {
array1[i] = 10;
array2[i] = 10;
array3[i] = 10;
if (i < 9) array4[i] = 10;
}
array3[5] = 9;
// First test
int result = compare_gen(array1, array2, sizeof(int), sizeof(array1), sizeof(array2), (&compare_ints));
printf("1 --> %d\n",result);
// Second test
result = compare_gen(array1, array3, sizeof(int), sizeof(array1), sizeof(array3), (&compare_ints));
printf("2 --> %d\n",result);
// third test
result = compare_gen(array1, array4, sizeof(int), sizeof(array1), sizeof(array4), (&compare_ints));
printf("3 --> %d\n",result);
return 0;
}
Indexing outside range
In the while(), wherever blockXsize is used, should be replaced with blockXsize/elem_size. Once this is done,i will index over its proper range. Further, the if ( elem_size == ... will the not be needed. Other simplifications are possible.
if (1)
{
while ( i < block1size/elem_size && i < block2size/elem_size)
{
//result = (*compare_it)((&((int*)block1)[i]),(&((int*)block2)[i]));
result = (*compare_it)(
(&((char*)block1)[i*elem_size]),
(&((char*)block2)[i*elem_size]));
if ( result == 0)
{
i++;
}
else if ( result == -1 || result == 1 )
{
return result;
}
}
if ( result == 0 )
{
if (i == block1size/elem_size && i == block2size/elem_size)
{
return result;
}
else if (i != block1size/elem_size && i == block2size/elem_size)
{
result = -1;
return result;
}
else
{
result = 1;
return result;
}
}

qsort works incorrectly (compare function)

I write program which sort numbers like 23.44 12.4223. And almost everything works fine but it does not sort correctly numbers for instance 24.321 and 24.33 i mean for my rpgoram 24.321 is greater than 24.33
Infile contains numbers like 34.5 123.55. 56. .43 564.3
Here's my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define NUMBER_CHUNK 13
char* getNumber(FILE* fp)
{
int length;
int current = 0;
int c;
char *number, *number2;
number = (char*)malloc(sizeof(char)*NUMBER_CHUNK);
if(!number)
{
printf("Error while allocating memory!\n");
return NULL;
}
length = NUMBER_CHUNK;
while(!isspace(c = fgetc(fp)) && !feof(fp))
{
if(isdigit(c) || c == '.')
{
number[current] = c;
current++;
if(current >= length)
{
length+=NUMBER_CHUNK;
number2 = (char*)realloc(number,sizeof(char*)*length);
if(number2 == NULL)
{
free(number2);
return NULL;
}
else number2 = number;
}
}
else
{
return NULL;
}
}
number[current] = '\0';
return number;
}
int compare(const void *str1, const void *str2)
{
char* curr1;
char* curr2;
int value = 0;
size_t len1 = 0;
size_t len2 = 0;
curr1=*(char**)str1;
curr2=*(char**)str2;
while(*curr1=='0' || *curr1=='.') curr1++;
while(*curr2=='0' || *curr2=='.') curr2++;
while(*curr1 || *curr2)
{
while(*curr1 == '.')
curr1++;
while(*curr2 == '.')
curr2++;
if(value == 0)
{
value = *curr1 - *curr2;
}
if(*curr1)
{
curr1++;
len1++;
}
if(*curr2)
{
curr2++;
len2++;
}
}
if(len1 != len2)
{
return (len1 > len2) ? 1 : -1;
}
return value;
}
int main(int argc, char** argv)
{
FILE* fp;
char** tab;
int i = 0;
int lines = 0;
int length = 10;
if(argc != 2)
{
printf("Incorrent syntax! Use ./program_name input_file\n");
return 1;
}
if(!(fp = fopen(argv[1],"r")))
{
printf("Could not open the file! Please try again!\n");
return 2;
}
tab = (char**)malloc(length*(sizeof(char*)));
if(!tab)
{
printf("Could not allocate memory!\n");
free(tab);
return 3;
}
while(!feof(fp))
{
tab[i] = getNumber(fp);
if(i >= length)
{
length += 10;
tab = (char**)realloc(tab,sizeof(char*));
if(tab == NULL)
{
free(tab);
return 5;
}
}
if(tab[i] == NULL)
{
printf("Incorrect character in the infile! Terminating\n");
free(tab);
return 4;
}
if(*tab[i] == '\0')
{
free(tab[i]);
i--;
}
i++;
lines = i;
}
printf("\nBEFORE\n");
for(i = 0 ; i < lines; i++)
{
printf("%s\n", tab[i]);
}
qsort(tab, lines, sizeof(char*), compare);
printf("\nAFTER\n");
for(i = 0; i < lines; i++)
{
printf("%s\n",tab[i]);
free(tab[i]);
}
printf("\n");
free(tab);
fclose(fp);
return 0;
}
In your program 24.321 is greater than 24.33 because length of 24.321 is greater than length of 24.33.
You should stop increasing length when you read ..
Fix:
//UPDATE
while(*curr1=='0') curr1++;
while(*curr2=='0') curr2++;
//END OF UPDATE
char dot1 = 0, dot2 = 0;
char err1 = 0, err2 = 0;
while(*curr1 || *curr2)
{
if(*curr1 == '.') ++dot1; //UPDATE2
if(*curr2 == '.') ++dot2; //UPDATE2
while(*curr1 == '.')
curr1++;
while(*curr2 == '.')
curr2++;
if(value == 0)
{
value = *curr1 - *curr2;
}
if(*curr1)
{
if(*curr1 < '0' || *curr1 > '9') err1 = 1;
curr1++;
if(!dot1) len1++;
}
if(*curr2)
{
if(*curr2 < '0' || *curr2 > '9') err2 = 1;
curr2++;
if(!dot2) len2++;
}
}
if(err1 || err2 || dot1 > 1 || dot2 > 1) exit(1); // UPDATE2
UPDATE:
I updated code. Now before main comparison while only zeros are skipped. Dots will be skipped at the beginning of main while and fix with dot1 and dot2 will work.
UPDATE2:
To check if numbers are correct you should count dots and check if all chars are dots or digits.
Be aware that for longer bad numbers (more than 255 dots) my code could not work correctly (because dot1 is 1 byte long). If you need to handle these cases you should check if dot1/dot2 are equal to 1 and change err1/err2 to 1 instead of increasing dot1/dot2.
Your problem is here:---
if(len1 != len2)
{
return (len1 > len2) ? 1 : -1;
}
For strings "24.321" len1 = 6 ,"24.33" len2 = 5 so the longest string wins.
I thing your algorithm will also encounter problems with 123.45 vs 23.456 as you are basically ignoring the decimal point.
You could try converting to floating point (use function atof() or strtof() ) to convert the string to a real real number then compare.
Or simply return "less than" if you encounter a '.' in the first string before you encounter it in the second string.

Resources