I am currently working on aa program whose goal is to take words from a file, and store them into an array, while outputting if they are at the beginning of a row, or a word on the line. The file looks like this: at the end of each line there is a final space, and a line break.
abbe able
abet abut
able abbe ably axle
ably abbe able ally
abut abbe abet
aced aces acid aged aped awed axed iced
aces aced acts ages ales apes axes ices
ache achy acme acne acre
achy ache ashy
The code that I have currently works in the terminal, outputting:
Row: abbe able,
Row: abet abut,
Row: able abbe, ably, axle,
Row: ably abbe, able, ally,
Row: abut abbe, abet,
Row: aced aces, acid, aged, aped, awed, axed, iced,
Row: aces aced, acts, ages, ales, apes, axes, ices,
Row: ache achy, acme, acne, acre,
Row: achy ache, ashy,
However, when I run it with valgrind, I run into an issue, it doesn't recognize rows, instead outputting only the first 2 letters as each row.
Row: abbe able,
ab, abut,
ab, abbe, ably, axle,
ab, abbe, able, ally,
ab, abbe, abet,
ac, aces, acid, aged, aped, awed, axed, iced,
ac, aced, acts, ages, ales, apes, axes, ices,
ac, achy, acme, acne, acre,
ac, ache, ashy,
After it finishes outputting all of the characters, it reads this:
*** stack smashing detected ***: terminated
==24==
==24== Process terminating with default action of signal 6 (SIGABRT)
==24== at 0x489818B: raise (raise.c:51)
==24== by 0x4877858: abort (abort.c:79)
==24== by 0x48E23ED: __libc_message (libc_fatal.c:155)
==24== by 0x49849B9: __fortify_fail (fortify_fail.c:26)
==24== by 0x4984985: __stack_chk_fail (stack_chk_fail.c:24)
==24== by 0x1094B0: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/test)
zo, boos, coos, moos, woos, zoom,==24==
==24== HEAP SUMMARY:
==24== in use at exit: 0 bytes in 0 blocks
==24== total heap usage: 19,833 allocs, 19,833 frees, 266,441 bytes allocated
==24==
==24== All heap blocks were freed -- no leaks are possible
==24==
==24== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Aborted (core dumped)
Here is the code. Any help would be greatly appreciated!!
int main(){
/* The Amount of words in each file, File 1, 2, 3 */
int totalWordQuantity = 19829;
/*the word that we test, we add by two because first 4: word, 5th: \n, 6th: \0*/
char word[5];
/*how many times we've changed the character*/
int letterSpot = 0;
/*Four Letter Word Document*/
FILE *flwd = fopen("WordDocuments/Four_Letter_Connections.txt", "r");
if(flwd == NULL){
printf("File Failed");
}
/* is it the first word of the line */
int wordCount = 0;
/* P is a step ahead of c, because otherwise the words get super messed up. */
int p = fgetc(flwd);
/*the character that goes through the file*/
int c = p;
/* So, this is a temporary word, who will store the row, so all of its category folks will be contained within it */
/*This stores all of the words*/
char** wordStorage = (char**)calloc(totalWordQuantity, sizeof(char*));
int i;
for(i = 0; i < totalWordQuantity; i++){
wordStorage[i] = malloc(sizeof(char) * 5);
}
int nextIsRow = 1;
/* First, take the character */
while(wordCount < totalWordQuantity){
p = fgetc(flwd);
/* Add the character to the word */
word[letterSpot] = (char)c;
/* Allows the letter spot to find the next place into the word */
letterSpot++;
if(c == ' '){
letterSpot = 0;
word[4] = '\0';
strcpy(wordStorage[wordCount], word);
if(nextIsRow == 1){
printf("\nRow: %s", wordStorage[wordCount]);
}
else{
printf(" %s,", wordStorage[wordCount]);
}
if(p == '\n'){
nextIsRow = 1;
p = fgetc(flwd);
}
else{
nextIsRow = 0;
}
wordCount++;
}
c=p;
}
fclose(flwd);
//Frees up word storage
for(i = 0; i < totalWordQuantity; i++){
free(wordStorage[i]);
}
free(wordStorage);
return 0;
Thank you for taking a look!
Some additional details: if I output something under the if(p == '\n')
line, it will not output in valgrind, however, it will in the terminal. Also, I've verified that it only puts words in allocated locations.
The following proposed code:
stderr
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LEN 1024
int main( void )
{
/*Four Letter Word Document*/
FILE *flwd = fopen( "WordDocuments/Four_Letter_Connections.txt", "r" );
if( flwd == NULL )
{
perror( "fopen Failed" );
exit( EXIT_FAILURE );
}
size_t rowCount = 0;
char lineBuf[ MAX_LINE_LEN ];
while( fgets( lineBuf, MAX_LINE_LEN, flwd ) )
{
// remove trailing '\n'
lineBuf[ strcspn( lineBuf, "\n" ) ] = '\0';
rowCount++;
printf( "Row: %4zu ", rowCount );
char *token = strtok( lineBuf, " " );
while( token )
{
printf( "%s, ", token );
token = strtok( NULL, " " );
}
printf( "\n" );
}
fclose( flwd );
return 0;
}
a run of the code, using the OPs listed input file results in:
Row: 1 abbe, able,
Row: 2 abet, abut,
Row: 3 able, abbe, ably, axle,
Row: 4 ably, abbe, able, ally,
Row: 5 abut, abbe, abet,
Row: 6 aced, aces, acid, aged, aped, awed, axed, iced,
Row: 7 aces, aced, acts, ages, ales, apes, axes, ices,
Row: 8 ache, achy, acme, acne, acre,
Row: 9 achy, ache, ashy,
Well, your code is a bit messy. And, its been hard to read. So, I would suggest try to clean your code and do things, those are only necessary. I'm providing a piece of code that does the same as your code. Take a look, and try to make your code better, and may be in the process it would be clear to you what is wrong:
Update:
Thanks to @AnttiHaapala, as (s)he pointed out. I was using char ch = fgetc()
, while, fgetc()
returns int
, which causes problems with specific compilers(which declares char
as unsigned).
Here's the updated code.
#include <stdio.h>
#include <stdlib.h>
#define BUF_SIZE 1024
int readLine(FILE *fp, char *buf) {
int i = 0;
int ch = fgetc(fp); // as fgetc() returns int
while(ch != '\n' && ch != EOF) {
buf[i++] = (char)ch; // cast 'ch' as 'char'
ch = fgetc(fp);
}
buf[i] = '\0';
// returns true if EOF is not found
// i.e. if line-break is the reason to terminate
return (ch == '\n');
}
int main() {
// declaring a buffer to hold a single line contents
char buf[BUF_SIZE];
char input[] = "input.txt";
FILE *fp = fopen(input, "r");
if(fp == NULL) {
printf("Can not open file\n");
exit(1);
}
int isLineBreak = 0; // by default declaring it false
do {
isLineBreak = readLine(fp, buf); // checking end line status
printf("%s\n", buf);
// run loop as long as you find line-break
// break only if you find EOF
} while(isLineBreak);
fclose(fp);
return 0;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.