My array does not reset to zero after I recall the function - c

I'm writing a word, character, line counter for files in C. Im using a function get_counts to get these numbers. Right now I'm trying to get these values for two files. However, when I call it twice, the values don't reset to zero. I don't understand why because I declare the array to be {0,0,0} before I do any counting when I call the function. Here is my code. Currently just trying to get the line counter to work in print_counts. i'm sending it two files, one file has 3735 lines and the other file has 21. I keep getting an output of 3756.
int *get_counts(char *filename)
{
FILE *file = fopen(filename, "r");
if (file == NULL)
{
printf("NULL FILE");
exit(1);
}
int c;
bool whitespace = true;
static int arr[3] = {0,0,0};
for(;;)
{
c = fgetc(file);
if (c == EOF)
{
break;
}
else if (c == '\n')
{
arr[0]++;
}
else if (whitespace && !isspace(c))
{
arr[1]++;
whitespace = false;
}
else if (!whitespace && isspace(c))
{
whitespace = true;
}
arr[2]++;
}
fclose(file);
return arr;
}
void print_counts(int* show, int *count, char *name)
{
if (name[0] != '\0')
{
//int *myArray1 = get_counts(&name[0]);
if (show[0] == 1)
{
printf("%d", count[0]);
}
}
if (name[1] != '\0')
{
if (show[0] == 1)
{
printf("%d", count[0]);
}
}
}
int main(int argc, char **argv)
{
int argArray[argc];
char *nameArray[argc];
for (int i = 1; i < argc; i ++)
{
if (strcmp(argv[i], "-l") == 0)
{
argArray[0] = 1;
}
if (strcmp(argv[i], "-w") == 0)
{
argArray[1] = 1;
}
if (strcmp(argv[i], "-c") == 0)
{
argArray[2] = 1;
}
if (strcmp(argv[i], "alice.txt") == 0)
{
nameArray[0] = "alice.txt";
}
if (strcmp(argv[i], "anh.txt") == 0)
{
nameArray[1] = "anh.txt";
}
if ((strcmp(argv[i], "-l") != 0) && (strcmp(argv[i], "-c") != 0 ) && (strcmp(argv[i], "-w") != 0 ) && (strcmp(argv[i], "-w") != 0) && (strcmp(argv[i], "alice.txt") != 0) && (strcmp(argv[i], "anh.txt") != 0))
{
printf("error");
exit(1);
}
}
int *myArrayAlice = get_counts(nameArray[0]);
print_counts(argArray, myArrayAlice, *nameArray);
int *myArrayAnh = get_counts(nameArray[1]);
print_counts(argArray, myArrayAnh, *nameArray);
return 0;
}

I don't understand why because I declare the array to be {0,0,0}
before I do any counting when I call the function.
Because is defined as static, remove the static keyword switching to int *arr = calloc(3, sizeof(int); or passing arr[3] from main and calling memset(arr, 0, 3 * sizeof(int)); in the function if you prefer to avoid dynamic memory.

Related

How to skip NULL file

My code traverses through command line arguments. if the command line contains "alice.txt" index zero of an empty array is filled with "alice.txt" This also applies to "anh.txt" if it is present, then index 1 is filled with "anh.txt". When i type in the command line ./wc alice.txt anh.txt it will print out words line and characters of both files. however if I just do /wc anh.txt i will get "NULL FILE" I suspect this is because of index zero being NULL, I wrote it so it would print "NULL FILE" and then exit the program. How can I modify my code so it doesn't exit, rather skips to the next index? This is what I have for code:
int main(int argc, char **argv)
{
int argArray[argc];
char *nameArray[argc];
for (int i = 1; i < argc; i ++)
{
if (strcmp(argv[i], "-l") == 0)
{
argArray[0] = 1;
}
if (strcmp(argv[i], "-w") == 0)
{
argArray[1] = 1;
}
if (strcmp(argv[i], "-c") == 0)
{
argArray[2] = 1;
}
if (strcmp(argv[i], "alice.txt") == 0)
{
nameArray[0] = "alice.txt";
}
if (strcmp(argv[i], "anh.txt") == 0)
{
nameArray[1] = "anh.txt";
}
if ((strcmp(argv[i], "-l") != 0) && (strcmp(argv[i], "-c") != 0 ) && (strcmp(argv[i], "-w") != 0 ) && (strcmp(argv[i], "-w") != 0) && (strcmp(argv[i], "alice.txt") != 0) && (strcmp(argv[i], "anh.txt") != 0))
{
printf("%s is an invalid argument or file\n", argv[i]);
}
}
if ((argArray[0] != 1) && (argArray[1] != 1) && (argArray[2] != 1))
{
argArray[0] = 1;
argArray[1] = 1;
argArray[2] = 1;
}
int *myArrayAlice = get_counts2(nameArray[0]);
print_counts(argArray, myArrayAlice, *nameArray);
printf(" alice.txt\n");
int *myArrayAnh = get_counts(nameArray[1]);
print_counts(argArray,myArrayAnh, *nameArray);
printf(" anh.txt\n");
int *myArrayTotal2 = get_counts2(nameArray[1]);
print_counts(argArray, myArrayTotal2, *nameArray);
printf(" total\n");
return 0;
}
int *get_counts(char *filename)
{
FILE *file = fopen(filename, "r");
if (file == NULL)
{
printf("NULL FILE");
//exit(1);
}
int c;
bool whitespace = true;
int *arr = calloc(3,sizeof(int));
for(;;)
{
c = fgetc(file);
if (c == EOF)
{
break;
}
else if (c == '\n')
{
arr[0]++;
}
else if (whitespace && !isspace(c))
{
arr[1]++;
whitespace = false;
}
else if (!whitespace && isspace(c))
{
whitespace = true;
}
arr[2]++;
}
fclose(file);
return arr;
}
int *get_counts2(char *filename)
{
FILE *file = fopen(filename, "r");
if (file == NULL)
{
printf("NULL FILE");
//exit(1);
}
int c;
bool whitespace = true;
static int arr[3] = {0,0,0};
for(;;)
{
c = fgetc(file);
if (c == EOF)
{
break;
}
else if (c == '\n')
{
arr[0]++;
}
else if (whitespace && !isspace(c))
{
arr[1]++;
whitespace = false;
}
else if (!whitespace && isspace(c))
{
whitespace = true;
}
arr[2]++;
}
fclose(file);
return arr;
}

Parsing argc and argv[] parameter in c

I have written the following program which is working fine when I compile the program in x86 configuration but when I change the configuration of the platform to x64, my program doesn't work at all. Where is the problem:
int main(int argc, char* argv[])
{
char* cp_UserName[MAX_PATH];
char* cp_DomainName[MAX_PATH];
char* cp_HashNtlm[MAX_PATH];
char* cp_ComputerName[MAX_PATH];
DnPthIconSetup();
DnPthInitialization(TRUE);
if (argc > 4)
{
for (size_t i = 1; i <= sizeof(argv); i++)
{
if (strstr(argv[i], "user") != NULL)
{
strtok_s(argv[i], ":", cp_UserName);
}
if (strstr(argv[i], "domain") != NULL)
{
strtok_s(argv[i], ":", cp_DomainName);
}
if (strstr(argv[i], "pc") != NULL)
{
strtok_s(argv[i], ":", cp_ComputerName);
}
if (strstr(argv[i], "ntlm") != NULL)
{
strtok_s(argv[i], ":", cp_HashNtlm);
}
}
printf("%s\n", *cp_UserName);
printf("%s\n", *cp_DomainName);
printf("%s\n", *cp_ComputerName);
printf("%s\n", *cp_HashNtlm);
system("PAUSE");
// ParametricCredentialDispatcher(cp_UserName, cp_DomainName, cp_HashNtlm, cp_ComputerName);
}
else if (argc == 1)
{
InteractiveMode();
}
else
{
printf("\nUsage: ./program user:[] domain:[] pc:[] ntlm:[]\n");
system("PAUSE");
}
return 0;
}
sizeof(argv) is a size of the pointer, not number of arguments.
Your usage of strstr will result into wrong result when, for example, the arguments contains pc:computer_for_an_user.
This usage of strtok_s will store pointer to the name of configurations, not their values.
Possible fix of the parsing part:
for (size_t i = 1; i < arc; i++)
{
if (strncmp(argv[i], "user:", 5) != NULL)
{
*cp_UserName = strchr(argv[i], ':') + 1;
}
if (strncmp(argv[i], "domain:", 7) != NULL)
{
*cp_DomainName = strchr(argv[i], ':') + 1;
}
if (strncmp(argv[i], "pc:", 3) != NULL)
{
*cp_ComputerName = strchr(argv[i], ':') + 1;
}
if (strncmp(argv[i], "ntlm:", 5) != NULL)
{
*cp_HashNtlm = strchr(argv[i], ':') + 1;
}
}
The added : in the arguments of strncmp is assuming that strchr won't return NULL.
Also you should initialize the pointers and check if they are not NULL before passing them to printf.

How to redesign this code to avoid goto

I have a programme that needs the user to input 4 files (no order require). Then I do something to the files differently. Now I used the goto statement, I want to replace the goto statement, but don't know how. And I want to know if these go to have some problem? Here is my code that using goto:
int main(int argc, char **argv){
char *tmp;
int i, flag1=0, flag2=0, flag3=0, flag4=0;
FILE *fp1;
FILE *fp2;
FILE *fp3;
FILE *fp4;
char file1[64];
char file2[64];
char file3[64];
char file4[64];
for( i=1; i<argc; i++){
tmp = argv[i];
if ( strcmp(tmp+8,"F1") == 0 ){
sprintf(file1,argv[i]);
flag1=1;
}
else if (strcmp(tmp+8,"F2") == 0 ){
sprintf(file2,argv[i]);
flag2=1;
}
else if (strcmp(tmp+8,"F3") == 0 ){
sprintf(file3,argv[i]);
flag3=1;
}
else if (strcmp(tmp+8,"F4") == 0 ){
sprintf(file4,argv[i]);
flag4=1;
}
}
if( !(flag1 && flag2 && flag3 && flag4) ){
printf("Must input four files!!\n");
exit(-1);
}
if (access(file1,0) != 0){
GOTO L1;
}
if((fp1 = fopen(file1,"r")) == NULL){
exit(-1);
}
do_file_1(fp1);
fclose(fp1);
L1: if (access(file2,0) != 0 ){
goto L2;
}
if((fp2 = fopen(file2,"r")) == NULL){
exit(-1);
}
do_file_2(fp2);
fclose(fp2);
L2: if (access(file3,0) != 0)
{
goto L3;
}
if((fp3=fopen(file3,"r"))==NULL)
{
exit(-1);
}
do_file_3(fp3);
fclose(fp3);
L3: if (access(file4,0) !=0)
{
goto end;
}
if((fp4=fopen(file4,"r"))==NULL)
{
exit(-1);
}
do_file_4(fp4);
fclose(fp4);
end:
return 0;
}
You have "if this condition is true, skip over some code". That's the only thing you're using goto for.
That's exactly what if does (except if skips the code if the condition is false).
You can replace:
L2: if (access(file3,0) != 0)
{
goto L3;
}
if((fp3=fopen(file3,"r"))==NULL)
{
exit(-1);
}
do_file_3(fp3);
fclose(fp3);
L3:
with:
if (access(file3,0) == 0)
{
if((fp3=fopen(file3,"r"))==NULL)
{
exit(-1);
}
do_file_3(fp3);
fclose(fp3);
}
and similarly for the other uses of goto.
You refactor in steps.
You can take the end label statement and put it directly where it is called. That's easy.
For the others, you can use else statements:
if (access(file1,0) != 0){
//GOTO L1;
}else{
if((fp1 = fopen(file1,"r")) == NULL){
exit(-1);
}
do_file_1(fp1);
fclose(fp1);
}
L1: if (access(file2,0) != 0 ){
//goto L2;
}else{
if((fp2 = fopen(file2,"r")) == NULL){
exit(-1);
}
do_file_2(fp2);
fclose(fp2);
}
L2: if (access(file3,0) != 0)
{
//goto L3;
}else{
if((fp3=fopen(file3,"r"))==NULL)
{
exit(-1);
}
do_file_3(fp3);
fclose(fp3);
}
L3: if (access(file4,0) !=0)
{
end:
return 0;
}
if((fp4=fopen(file4,"r"))==NULL)
{
exit(-1);
}
do_file_4(fp4);
fclose(fp4);
Of course, since there is no other statements in the if statements, the if else can be refactored to just be an if.
I have broken down more complex problems like this in the past.
Perhaps an approach like the following which uses loops with arrays would be shorter and more compact. This is a fairly straightforward transformation that consolidates separate variables into arrays. This does use an array of function pointers (see How do Function pointers in C work).
The do_file_1(), do_file_2(), etc. functions are just place holders for the actual functions you are using. This keeps the literal file names ("F1", "F2", etc.) that you specify though I am not sure why you are requiring certain, specific file names.
I also use the strcpy() function to copy the file name argument into the array of file names to open rather than using the sprintf() function.
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
void do_file_1 (FILE *fp)
{
printf ("function do_file_1 called.\n");
}
void do_file_2 (FILE *fp)
{
printf ("function do_file_2 called.\n");
}
void do_file_3 (FILE *fp)
{
printf ("function do_file_3 called.\n");
}
void do_file_4 (FILE *fp)
{
printf ("function do_file_4 called.\n");
}
int main(int argc, char **argv)
{
int i;
char *fileArray[4] = { "F1", "F2", "F3", "F4"};
char fname[4][64] = {0};
void (*funcs[4]) (FILE *fp) = {do_file_1, do_file_2, do_file_3, do_file_4};
for( i = 1; i < argc; i++) {
int j;
for (j = 0; j < 4; j++) {
if ( strcmp(argv[i], fileArray[j]) == 0 ) {
strcpy(fname[j],argv[i]);
break;
}
}
}
if( !(fname[0][0] && fname[1][0] && fname[2][0] && fname[3][0]) ) {
printf("Must input four files!!\n");
exit(-1);
}
for (i = 0; i < 4; i++) {
if (access(fname[i],0) == 0) {
FILE *fp = fopen(fname[i],"r");
if (fp != NULL) {
funcs[i](fp);
fclose(fp);
} else {
break;
}
} else {
break;
}
}
if (i < 4) exit(-1);
return 0;
}
the obvious variant is to change if statements like this:
if (access(file1,0) == 0){
if((fp1 = fopen(file1,"r")) == NULL) exit(-1);
do_file_1(fp1);
fclose(fp1);
}
if (access(file2,0) == 0 ){
if((fp2 = fopen(file2,"r")) == NULL) exit(-1);
do_file_2(fp2);
fclose(fp2);
}
...
You're just using goto's as a way to reverse the if clauses. Reverse them directly and indent what lies between:
if (access(file1,0) != 0){
GOTO L1;
}
if((fp1 = fopen(file1,"r")) == NULL){
exit(-1);
}
do_file_1(fp1);
fclose(fp1);
L1: ...
Becomes:
if (access(file1,0) == 0)
{
if((fp1 = fopen(file1,"r")) == NULL){
exit(-1);
}
do_file_1(fp1);
fclose(fp1);
}
//L1:
int main(int argc, char **argv){
char *tmp;
int i, flag1=0, flag2=0, flag3=0, flag4=0;
FILE *fp1;
FILE *fp2;
FILE *fp3;
FILE *fp4;
char file1[64];
char file2[64];
char file3[64];
char file4[64];
for( i=1; i<argc; i++){
tmp = argv[i];
if ( strcmp(tmp,"F1") == 0 ){
sprintf(file1,argv[i]);
flag1=1;
}
else if (strcmp(tmp,"F2") == 0 ){
sprintf(file2,argv[i]);
flag2=1;
}
else if (strcmp(tmp,"F3") == 0 ){
sprintf(file3,argv[i]);
flag3=1;
}
else if (strcmp(tmp,"F4") == 0 ){
sprintf(file4,argv[i]);
flag4=1;
}
}
if( !(flag1 && flag2 && flag3 && flag4) ){
printf("Must input four files!!\n");
return -1;
}
if (access(file1,0) == 0) {
if((fp1 = fopen(file1,"r")) == NULL){
return -1;
}
do_file_1(fp1);
fclose(fp1);
}
/*L1:*/
if (access(file2,0) == 0 ) {
if((fp2 = fopen(file2,"r")) == NULL){
return -1;
}
do_file_2(fp2);
fclose(fp2);
}
/*L2:*/
if (access(file3,0) == 0) {
if((fp3=fopen(file3,"r"))==NULL) {
return -1;
}
do_file_3(fp3);
fclose(fp3);
}
/* L3: */
if (access(file4,0) == 0) {
if((fp4=fopen(file4,"r"))==NULL) {
return -1;
}
do_file_4(fp4);
fclose(fp4);
}
return 0;
}
But really, no one programer will not do so.

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.

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