fgets() won't read content from file to 2d array - c

The fgetsstatement is not gathering anything from the calendarLog file stream into the events[][] array. My calendarLog.txt has five lines in it:
1/1/1 fds
2/2/2 dsa
3/3/3 sal
4/4/4 444
5/5/5 555
The printf statement is instructed to output one ! as well as the events[counter], however, my output statement is only the question marks, !!!!!, five of them (if I add more lines to calendarLog, it prints more exclamation points). Why does
while(fgets(events[counter++], EVENT_DESCR_SIZE, calendarLog) != NULL)
remain true and yet printf("!%s", events[counter]) not print the events[counter]?
All help appreciated!
FILE *calendarLog;
char events[MAX_EVENTS][EVENT_DESCR_SIZE],
*newLinePos;
int counter = 0,
index1,
index2;
for (index1 = 0; index1 < MAX_EVENTS; index1++)
for (index2 = 0; index2 < EVENT_DESCR_SIZE; index2++)
events[index1][index2] = 0;
if ((calendarLog = fopen("calendarLog.txt", "r")) == NULL)
{
calendarLog = (fopen("calendarLog.txt", "w"));
fprintf(calendarLog, "s\n", eventObject);
}
else
{
while (fgets(events[counter++], EVENT_DESCR_SIZE, calendarLog) != NULL)
{
if ((newLinePos = strchr(events[counter], '\n')) != NULL) //takes the '\n' out
*newLinePos = '\0'; //of the events[counter]
printf("!%s", events[counter]);
}

This should tell you everything you need to know about how to fix the problem:
FILE *calendarLog;
char events[MAX_EVENTS][EVENT_DESCR_SIZE];
char *newLinePos;
int counter = 0;
int index1;
int index2;
// initialize the array: events[][]
for (index1 = 0; index1 < MAX_EVENTS; index1++)
for (index2 = 0; index2 < EVENT_DESCR_SIZE; index2++)
events[index1][index2] = 0;
if ((calendarLog = fopen("calendarLog.txt", "r")) == NULL)
{ // fopen failed
calendarLog = (fopen("calendarLog.txt", "w"));
fprintf(calendarLog, "%s\n", eventObject); // 's' should be '%s
}
else
{ // fopen successful
while (fgets(events[counter++], EVENT_DESCR_SIZE, calendarLog) != NULL)
{
// following 'if' is looking at 'next' events because counter is already updated
// replace '\n' with null to terminate string for following printf
if ((newLinePos = strchr(events[counter], '\n')) != NULL)
*newLinePos = '\0';
// print the value
printf("!%s", events[counter]);
}
}

Related

Brain**** implementation in C

I'm trying to run a hello world program with the brainfuck implementation that I made this week but I'm getting a strange output.
This is the hello world file that I'm trying to run.
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.-------
-.>>+.>++.
I have saved it to hello.txt, and am parsing it in the main function of the program.
The output is
1 -3 4 4 7 0 -1 7 10 4 -4 1 2
which, when you add 72, and convert to character , gives
I E L L O H G O R L D I J
So it seems like there is something I'm missing, even though its sort of close to the right solution.
But I'll go into the structure of the thing anyhow, the general idea is as followed:
We have two 'tapes', a program to follow which I label 'parsed' which has a pointer 'attached' to it, and an empty tape to write into, which I label 'mem', which also has a pointer 'attached' to it. We also have a list of structures that we can use to jump between bracket locations.
In the main function, there are three parts: first I parse the program and store it in an array. Then I run through this parsing and match brackets, then I start the brainfuck loop and write the output onto the empty array, until the final character has been reached.
In the brainfuck loop, when we find a bracket, we run through the list of pairs to find its match, and then jump to that location.
Maybe it's a bit clunky, but I hope it makes sense.
#include <stdio.h>
#include <stdlib.h>
#define MAX 30000
//input tape
char parsed[MAX];
char * ptr;
//bracket matching
struct bracketlinks{
char * bracket_1;
char * bracket_2;
};
struct bracketlinks * pairslist;
int bracket_count;
//output tape
char mem[MAX] = {0};
int * mptr;
int main(){
mptr = malloc(sizeof(int));
//parse text file and make list of tokens
FILE * parsecode;
parsecode = fopen("helloworldbf.txt", "r");
int count = 0;
char buffer;
while(!feof(parsecode)){
buffer = fgetc(parsecode);
if(buffer == 10){break;}
if(buffer == 32){continue;}
else{
parsed[count] = buffer;
if(buffer == 91 || buffer == 93){
bracket_count++;
}
count++;
}
}
fclose(parsecode);
pairslist = malloc(bracket_count * sizeof(char*));
//creates array of structures which match brackets so we can perform memory jumps
int reset_count;
int list_counter = 0;
for(int i = 0; i < count; i++){
if(parsed[i] == '['){
reset_count = 0;
for(int j = 0; j < count - i + 1; j++){
if(parsed[i + j] == '['){reset_count++;}
if(parsed[i + j] == ']'){reset_count--;}
if(reset_count == 0){
struct bracketlinks new;
new.bracket_1 = &parsed[i];
new.bracket_2 = &parsed[i + j];
pairslist[list_counter] = new;
list_counter++;
break;
}
else{continue;}
}
}
else{continue;}
}
//runs through the input tape and performs operations on the output tape
ptr = parsed;
char final_token = ptr[count];
while(ptr[0] != final_token){
if(ptr[0] == '['){
if(mem[mptr[0]]){++ptr;}
if(!mem[mptr[0]]){
for(int i = 0; i < bracket_count/2; i++){
if(pairslist[i].bracket_1 == &ptr[0]){
ptr = ++pairslist[i].bracket_2;
}
if(pairslist[i].bracket_2 == &ptr[0]){
ptr = ++pairslist[i].bracket_1;
}
else{continue;}
}
}
}
if(ptr[0] == ']'){
if(!mem[mptr[0]]){
for(int i = 0; i < bracket_count/2; i++){
if(pairslist[i].bracket_1 == &ptr[0]){
ptr = ++pairslist[i].bracket_2;
}
if(pairslist[i].bracket_2 == &ptr[0]){
ptr = ++pairslist[i].bracket_1;
}
else{continue;}
}
}
if(mem[mptr[0]]){++ptr;}
else{continue;}
}
if(ptr[0] == '+'){++ptr;++mem[mptr[0]];}
if(ptr[0] == '-'){++ptr;--mem[mptr[0]];}
if(ptr[0] == '>'){++ptr; mptr[0]++;}
if(ptr[0] == '<'){mptr[0]--;++ptr;}
if(ptr[0] == '.'){++ptr; printf("%c %d \n", mem[mptr[0]] + 72, mem[mptr[0]]);}
else{continue;}
}
free(pairslist);
free(mptr);
return 0;
}
Any help would be massively appreciated,
Cheers..
OK so here's the fix for the main bug: basically just switch the exclamation marks and don't be a numpty.
if(ptr[0] == ']'){
if(mem[mptr[0]]){
for(int i = 0; i < bracket_count/2; i++){
if(pairslist[i].bracket_1 == &ptr[0]){
ptr = ++pairslist[i].bracket_2;
}
if(pairslist[i].bracket_2 == &ptr[0]){
ptr = ++pairslist[i].bracket_1;
}
else{continue;}
}
}
if(!mem[mptr[0]]){++ptr;}
else{continue;}
}
Still working on the !feof thing but will update with that too

C stack corrupted for a string var

So as a part of a class project, I'm supposed to receive an input string from the user and to varies actions on it. For some reason, I get a stack corrupted error in the following code.
void main()
{
char cmd[80] = "", substr[81] = "", matrixName1[11], matrixName2[11], substrFrob[11] = "";
int start = 0, end = 0, cmdSort, i, j, prog = 0, row = 0, col, row1, row2, col1, col2, **matrix1, **matrix2, trace = 0, words, matrixNum = 0;
memset(matrixName1, 0, strlen(matrixName1)); //reseting variables
memset(matrixName2, 0, strlen(matrixName2));
printf_s("#");
fgets(cmd, sizeof(cmd), stdin);
words = wordCounter(cmd);
start = end;
stringCutter(substr, cmd, &start, &end);
while (1)
{
if (prog == 0) //sorting for command and number of args
{
if (!strcmp(substr, "exit") && words == 1) break;
else if (!strcmp(substr, "zeroes") && words == 4) cmdSort = 1;
else if (!strcmp(substr, "set") && words > 1) cmdSort = 2;
else if (!strcmp(substr, "echo") && words == 2) cmdSort = 3;
else if (!strcmp(substr, "frob") && words == 3) cmdSort = 4;
/* rest of the code*/
if (matrixName1[0] != 0) //freeing memory
{
for (i = 0; i < row1; i++)
free(matrix1[i]);
free(matrix1);
}
if (matrixName2[0] != 0)
{
for (i = 0; i < row2; i++)
free(matrix2[i]);
free(matrix2);
}
//system("cls");
//exit(0);
now as a part of the project we can't use any function within stdlib.h expect malloc and free. once I removed the exit(0), I started to receive an error when the user enters "exit" -
"Run time check Failure #2 stack around the variable 'substr' was corrupted"
but for the life of me, I can't find whats wrong.
thank in advence.
I couldn't check your code but it's likely that you are not allocating enough space for the char arrays. Trying to write to the char array that was not previously allocated can corrupt stack cookies hence the error.
If you had provided the full code I would try running it. In this case I can only guess :)
Edit: You might not be using the strlen right. You should be using "sizeof(char) * charcount " instead on memset calls.

Format any number in Indian currency style using C language

Indian Currency format is 12345 → "12,345" (for odd length) and 123456 → "1,23,456" (for even length). I have included all possibilities such as
1. Minus sign: "-12,345".
2. Decimal Point: "-12,345.345" or "12,345.123".
3. Zero Condition 000000.123 → "0.123".
4.Minus and Zero Condition '-000000.123' -> "-0.123"
int currencyFormatter(char av_currency[], int av_strLen, char *ap_formattedNumber)
{
char flag = 'N'; //Taking a Flag to know whether thier is a decimal Point in Currency or not
int lengthOf = 0, index = 0, i = 0, j = 0;
char *decAr = NULL;
char *tmpCurrency = NULL;//Taking two Pointers one for Array with Commas(tmpCurrency) and decAr pointer for decimal Point array
char *s = NULL;
s = strstr(av_currency, ".");//Checking for decimal Point in array
if (s > 0)
{
flag = 'D'; // Changing Flag to show Decimal Point is Present in Array
s = strchr(av_currency, '.');
index = s - av_currency; //Index at which Decimal Point is present
av_strLen = strlen(av_currency) - index; // calculated formula to know length of an array needed to contain decimal point and Numbers after that
decAr = (char*)malloc(av_strLen*sizeof(char*));//allocated Memory using malloc
decAr[av_strLen] = '\0';
memmove(decAr, &av_currency[index], av_strLen); //memmove from decimal till end of array.
av_currency[index] = '\0';
if (!decAr)//Handled Null Condition for Pointer
{
return -1;//All errors for Negative Number
}
}
lengthOf = strlen(av_currency) + (strlen(av_currency) / 2); // Derived Formula(It Works for Indian Currency Format) to know the length of an array is needed to contain numbers and Commas Together.
tmpCurrency = (char*)malloc(lengthOf*sizeof(char*));
strrev(av_currency); //Reversed Array as commas comes at multiple of 3. eg=12345 reverse=54321 wdComma=543,21 index is 3 if number would had been bigger commas would had come at 3,6.
while (av_currency[i] != '\0')
{
if (j % 3 == 0 && j >= 3 && av_currency[i] != '-')//all Commas come at multiple of 3 when you reverse an amount
{
tmpCurrency[j] = ',';//If an , is found Increment only J as
is used as index number to store in tmpcurrency
j++;
continue;
}
tmpCurrency[j] = av_currency[i];//storing the Value in tmpCurrency
i++;//Incrementing
j++;//Incrementing
}
tmpCurrency[j] = '\0';//Null Condition
if (!tmpCurrency) // Checking for NULL Pointer
{
return -2; //all errors for Negative value
}
flag == 'D' ? strcpy(av_currency, (strcat(strrev(tmpCurrency), decAr))) : strcpy(av_currency, (strrev(tmpCurrency)));//Ternary Operator
strcpy(ap_formattedNumber,av_currency);//Copying formated number into original array
free(tmpCurrency);//Releasing the memory
free(decAr);//Releasing the Memory
return 0;
}
I have solution for above question.
Please try this code.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
char *printComma(double input_number,char *demo,char ap_it[],char ap_type[])
{
char *result = NULL;
char *lp_decimal_number = NULL;
char *main_number = NULL;
char *decimal_pos = NULL;
char zero[1] = {0};
int i = 0;
int j = 0;
int z = 0;
int cnt = 0;
int decimal_index = 0;
int lp_decimal_numberLen = 0 ;
int flag_dec = 0;
int flag_minus = 0 ;
int length_main;
int k = 0;
int length_demo=0;
sprintf(demo,"%lf",input_number);
if(strcmp(ap_type,"P") == 0)
{
if(strcmp(ap_it,"A") == 0 || strcmp(ap_it,"B") == 0)
{
sprintf_s(demo,40,"%0.4lf",input_number);
}
else
{
sprintf_s(demo,40,"%0.2lf",input_number);
}
}
else
{
sprintf_s(demo,40,"%.0lf",input_number);
}
length_demo = strlen(demo); // finds the length of original string
result = (char *)malloc((length_demo+10)*sizeof(char));
main_number = (char *)malloc((length_demo+50)*sizeof(char));
z = strspn(demo[0] == '-' ? (demo + 1) : demo , "0");
if(z != 0)
{
if(demo[0] != '-')
{
memcpy(main_number,&demo[z],length_demo);
main_number[length_demo]='\0';
}
else
{
puts(main_number);
main_number[length_demo]='\0';
flag_minus=1;
}
}
else
{
memcpy(main_number,&demo[0],length_demo);
main_number[length_demo]='\0';
}
length_main=strlen(main_number);
decimal_pos = strstr(main_number,".");
if(decimal_pos > 0)
{
decimal_index = decimal_pos - main_number ; // Getting postion of decimal
lp_decimal_numberLen = length_main - decimal_index; // Calculating the endpoint for decimal number
if(length_main > 3) //Copying the decimal part to a separate array
{
lp_decimal_number = (char *) malloc(lp_decimal_numberLen+1);
memcpy( lp_decimal_number, &main_number[decimal_index], lp_decimal_numberLen );
lp_decimal_number[lp_decimal_numberLen] = '\0';
flag_dec=1;
main_number[decimal_index]='\0';
}
}
//logic for comma starts here
strrev(main_number);
i = 0;
while(main_number[i] != '\0')
{
if (j%3 == 0 && j>=3 && main_number[i]!='-' && main_number[i]!='$')
{
result[j] = ',';
cnt++;
j++;
continue;
}
else if(cnt==1 || cnt==2)
{
result[j] = main_number[i];
}
else
{
result[j] = main_number[i];
}
i++;
j++;
}
result[j] = '\0';
if(flag_dec==0)
{
if(flag_minus==0)
return(strrev(result));
else
{
strcat(result,"-");
return(strrev(result));
}
}
else
{
if(flag_minus==0)
return(strcat(strrev(result),lp_decimal_number));
else
{
strcat(result,"-");
return(strcat(strrev(result),lp_decimal_number));
}
}
}
int main()
{
double number;
char num[25] = {0};
char it_type[] = "A";
char ap_type[] = "P";
char *formattedNumber = NULL;
printf("\n Enter the number n: ");
scanf("%lf",&number);
formattedNumber=printComma(number,num,it_type,ap_type);
printf("\n Final Result = %s ",formattedNumber);
getch();
return 0;
}
Do only positive values with your function!
Check if the value is negative before calling the function; call the function with the positive value; if it was negative to start with, add the minus sign afterwards.
int needssign = 0;
if (val < 0) needssign = 1;
indianformat(res, abs(val));
if (needssign) sprintf(res, "-%s", res);
Or make your current function a helper function and use the code above for the new improved function for formatting in Indian format.

C - reading multiple file streams

Im writing my own simplified version of the classic UNIX program 'wc' (word count). It counts number of lines, words, and characters. All these features work fine. But where i run into trouble is when im trying to read multiple files from *argv[x]. I need to make every variable into an array, and run the whole process through loops to achieve what im looking for.
My program returns a segmentation fault. Something is not being assigned into the arrays at some point in the code, and i can't seem to figure out exactly where that is.
Any help is much appreciated :)
/*
* [PROGRAM] wc (word count)
* [AUTHOR] Jesper M. Olsen # jm0.codes
* [DATE] September 9th 2015
* [PURPOSE] Returns number of lines, words, and characters in a file
*
* [DESCRIPTION] This program is meant to be utilized as a handy little browsing tool.
* For instance, while moving through the filesystem of a programming archive,
* just type 'wc <filename>' and you will get number of lines, words and characters returned promptly.
*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc == 1)
return -1;
int numL[argc]; /* initialize array value placeholders */
int numW[argc];
int numC[argc];
int getC[argc];
int getW[argc];
int setNull;
for (setNull = 1; setNull <= argc-1; setNull++) { /* assign ZERO to value placeholders */
numL[setNull] = 0;
numW[setNull] = 0;
numC[setNull] = 0;
getW[setNull] = 0;
}
int x;
FILE *fOp[argc-1];
for (x = 1; x <= argc-1; x++) { /* open file stream for each file */
fOp[x] = fopen(argv[x], "r");
if (fOp[x] == NULL)
return -1;
}
int y;
for (y = 1; (getC[y] = getc(fOp[y])) != EOF; y++) {
if (getC[y] == '\n') numL[y]++;
if (getC[y] == ' ' || getC[y] == '\n' || getC[y] == '\t') getW[y] = 0;
else if (getW[y] == 0) {
getW[y] = 1;
numW[y]++;
} numC[y]++;
}
int z;
for (z = 1; z <= argc-1; z++) { /* close files */
fclose(fOp[z]);
}
int c;
for (c = 1; c <= argc-1; c++) {
printf("[%s] %dL %dW %dC\n", argv[c], numL[c], numW[c], numC[c]);
}
return 0;
}
This will cause a segfault when you reach the last file
FILE *fOp[argc-1];
for (x = 1; x <= argc-1; x++) { /* open file stream for each file */
fOp[x] = fopen(argv[x], "r");
if (fOp[x] == NULL)
return -1;
}
because the array is not large enough. It should be
FILE *fOp[argc];
The mistake would be easier to see if you used
< argc
instead of
<= argc-1
in your loops.
I think problem may be
here -
for (y = 1; (getC[y] = getc(fOp[y])) != EOF; y++) {
if (getC[y] == '\n') numL[y]++;
if (getC[y] == ' ' || getC[y] == '\n' || getC[y] == '\t') getW[y] = 0;
else if (getW[y] == 0) {
getW[y] = 1;
numW[y]++;
} numC[y]++;
}
As arrays can argc number of elements but with this loop you may have read and stored integers more than argc in getC . Thus getting Seg Fault .
But we don't know what it inside files we can't be sure.
Try increasing size of arrays .
Note - It is better to initialize array starting with index 0. In this code you haven't use index 0.

C: Help with Custom strpos() Function

I have the following function:
int strpos(const char *needle, const char *haystack)
{
int neLen, haLen, foundPos, nePos, i;
char temp;
neLen = strlen(needle);
haLen = strlen(haystack);
if(haLen < neLen)
return -1;
nePos = 0;
foundPos = -1;
i = 0;
while((temp = *haystack++) != '\0'
&& (i < (haLen-neLen+1) || foundPos > -1)
&& nePos < neLen)
{
if(temp == *needle+nePos)
{
if(nePos == 0)
foundPos = i;
nePos++;
}
else
{
nePos = 0;
foundPos = -1;
}
i++;
}
return foundPos;
}
It works properly when I search for a single character:
printf("Strpos: %d\n", strpos("a", "laoo")); // Result: "Strpos: 1"
But it improperly with longer string:
printf("Strpos: %d\n", strpos("ao", "laoo")); // Result: "Strpos: -1"
What is the problem?
Bonus question: is the while loop properly broken into multiple lines? What is the accepted way to do this?
EDIT: strlen() is, naturally, a custom function that returns the length of the string. This works properly.
Each time you go round the loop you get the next character from haystack. So if needle has two characters by the time you have finished comparing needle with the substring of haystack beginning at position 0, the haystack pointer is pointing at position 2 (for a two character needle).
This means that you skip comparing needle with the substring of haystack beginning at position 1.
The solution is of the standard bang-your-head-against-the-wall-in-an-infinite-loop-and-wonder-why-the-hell-you're-a-programmer variety.
if(temp == *needle+nePos)
Should be:
if(temp == *(needle+nePos))

Resources