Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Basically what I'm doing is reading in a random text file, removing the punctuation and arranging the words into a linked list.
Everything works fine using this
printf("%c", (*(buf+x)));
so for example, the text file has the following
"they're their where ever we may go go,"
the correct out put is printed
theyre
their
where
ever
we
may
go
go
My problem is, how do I convert these into strings and store them in an array?
I'm assuming you want to reuse buf, so you want to copy the words into separately allocated storage. If you terminate each word in buf with a null byte prior to copying it, i.e. '\0', then you can use strdup to copy it. You can later free the space with free. Add the following includes (the second is for free):
#include <string.h>
#include <stdlib.h>
Here's a simple example:
buf[0] = 'a';
buf[1] = 'b';
buf[2] = 'c';
buf[3] = '\0';
str = strdup(buf);
I assume you want to store the words from the file in an array and print them.
you can try the following:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char *buf[40];
for (int n = 0; n < 40; n++)
{
buf[n] = (char*)malloc(20 * sizeof(char));
}
FILE *file;
fopen_s(&file, "file.txt", "r");
int c, i = 0, j = 0;
bool init = 0;
while ((c = getc(file)) != EOF)
{
if (c != ' ')
{
buf[i][j] = c;
j++;
init = 1;
}
else
{
if (init)
{
buf[i][j] = '\0';
i++;
j = 0, init = 0;
}
}
}
buf[i][j] = '\0';
for (int x = 0; x <= i; x++)
{
printf("word[%d] : %s\n", x, buf[x]);
}
for (int x = 0; x < 40; x++)
{
free(buf[x]);
}
fclose(file);
return 0;
}
Try this code to understand better concept :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char c;
int i = 0, count = 0,max = 0;
FILE *fp;
fp = fopen("file.txt", "r");
if(fp == 0)
{
printf("File is not opened\n");
return;
}
else
{
// Finding line having maximum characters from the file to allocate that much memory..
while ((c = getc(fp)) != EOF)
{
count++;
if(c == '\n')
{
if(count > max)
max = count;
count = 0;
}
else
{
count = 0;
}
}
}
rewind(fp);
// Allocating the memory up to max line from the file.
char *temp = (char*)malloc(max * sizeof(char));
while ((c = getc(fp)) != EOF)
{
if ((c >= 'a' && c<='z') || (c >= 'A' && c <= 'z'))
{
temp[i++] = c;
}
else if(c == ' ' || c == '\n')
{
temp[i] = '\0';
printf("%s\n",temp);
i = 0;
memset(temp,'\0',max);
}
}
free(temp);
fclose(fp);
return 0;
}
Related
I have a program, which receives filename as an input, saves file contents into 2d char array and then outputs words. It works absolutely fine for about 400 words, but then, when I add more words, it crashes. Debugging showed that i am trying to access unused address, and I don't understand how is that possible considering that previous tests with lesser amount of words were successful.
The question is: what am i missing here?
FILE: functions.c
#include "Lab10.h"
#include <stdio.h>
#include <malloc.h>
char** parser(char* filename) {
FILE* fp;
fp = fopen(filename, "r");
char** str = (char**)calloc(N, sizeof(char*) * N);
if (!str)
{
printf("\n Allocation error");
return NULL;
}
char ch;
int space = 0, words = 0;
for (int i = 0; !feof(fp); i++) // Memory allocation
{
ch = fgetc(fp);
if (!is_ch(ch))
{
if (i != space)
{
if (!(str[words] = (char*)calloc(i - space, sizeof(char) * (i - space))))
{
printf("\n Allocation error");
return NULL;
}
words++;
}
while (!is_ch(ch) && !feof(fp))
{
ch = fgetc(fp);
i++;
}
if(!feof(fp))
fseek(fp, -(int)sizeof(char), 1);
i--;
space = i;
}
}
fseek(fp, 0, SEEK_SET);
for (int i = 0; i < words; i++) // Copying words into 2d array
{
while (!is_ch(fgetc(fp)));
if (!feof(fp))
fseek(fp, -(int)sizeof(char), 1);
int j = 0;
do {
if (((fscanf(fp, "%c", &str[i][j])) != 1))
break;
j++;
} while (is_ch(str[i][j-1]) && !feof(fp));
}
return str;
}
int is_ch(char ch)
{
return ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'));
}
FILE: main.c
#define _CRT_SECURE_NO_WARNINGS
#include "Lab10.h"
#include <stdio.h>
#include <stdlib.h>
int main() {
char* filename = (char*)malloc(sizeof(char) * N);
if (!scanf("%s", filename) || filename == 0)
{
printf("\n Incorrect filename input");
return -1;
}
char** str = parser(filename);
printf("\n Contents of .txt file:");
for (int i = 0; str[i] != NULL; i++) {
printf("\n\t%d) ", i+1);
for (int j = 0; is_ch(str[i][j]); j++) {
printf("%c", str[i][j]);
}
}
return 0;
}
This answer was posted as a reply to one of the comments below the question itself. I tried writing readWord function, which recieves filepointer, reads one word and then returns pointer to the resulting array - that's eases the procedure, making it less complex. It works almost like fgets(), but it reads till non-character, instead of a newline
readWord function itself:
char* readWord(FILE* fp) {
char ch = 0;
while (!is_ch(ch))
{
ch = fgetc(fp);
if (ch == EOF || !ch)
return NULL;
}
int size = 1;
while (is_ch(ch))
{
if ((ch = fgetc(fp)) == EOF || !ch)
break;
size++;
}
fseek(fp, -(size * (int)sizeof(char)), 1);
if (ch != EOF || !ch)
size--;
char* word = (char*)calloc(size, sizeof(char) * size + 1);
if (!word)
{
printf("\n Allocation error.");
return NULL;
}
for (int i = 0; i < size; i++)
word[i] = fgetc(fp);
word[size] = '\0';
return word;
}
That's how i use it in main():
FILE* fp = fopen("test.txt", "r");
char* word;
while ((word = readWord(fp)) != NULL)
{
for (int i = 0; word[i] != '\0'; i++)
printf("%c", word[i]);
printf(" ");
}
Is there is anything i need to improve here? It works fine, but is it possible to somehow make it better?
Currently I am making a project that uses char arrays that have null elements. I want to be able to get the length of the array, in the sense of the number of elements that aren't null. This seemed reasonably trivial and I made this function:
int getWordLen(char word[]) {
int count = 0;
for (int i = 0; i < 512; i++) {
if (word[i] != '\0') {
count++;
}
}
printf("%d ", count);
return count;
}
However, every char array returns a length of 188. Any help would be appreciated.
This is the function I was calling it from:
void redact(Words * redactWords, char fileName[]) {
FILE * file = fopen(fileName, "r");
FILE * outputFile = fopen("outputFile.txt", "w+");
char word[512];
int i = 0;
char c;
while (c != EOF) {
c = getc(file);
if ((c > 96) && (c < 123)) {
word[i] = c;
i++;
continue;
}
else if ((c > 64) && (c < 91)) {
word[i] = c + 32;
i++;
continue;
}
i = 0;
if (isWordRedactWord(redactWords, word)) {
//write stars to file
char starStr[512];
for (int i = 0; i < getWordLen(word); i++) {
starStr[i] = '*';
}
fputs(starStr, outputFile);
}
else {
//write word to file
fputs(word, outputFile);
}
strcpy(word, emptyWord(word));
}
fclose(file);
fclose(outputFile);
}
In the initial while, I would only use while(!EOF).
Also, I believe you are using a lot more resources than necessary with the implementation of that for inside the while:
char starStr[512];
for (int i = 0; i < getWordLen(word); i++) {
starStr[i] = '*';
I suggest you to put it outside the while loop and see what happens.
If it is always giving you 188 of lenght, it is counting something that's constant, and may be related to that outer loop.
Hope you can solve it!
I wrote this program that replaces two spaces with an '*'.
How do I modify the code so that it does the same thing regardless of the string size? Is it even possible only using putchar and getchar?
#include <stdio.h>
int c;
char buffer[256];
int counter= 0;
int i;
int main()
{
while ((c = getchar()) != '\n'&&c!=EOF) {
buffer[counter] =c;
counter++;
if (counter >=255) {
break;
}
}
for(i=0; i<256; i++) {
if(buffer[i]== ' '&&buffer[i+1]==' ')
{
buffer[i]= '*';
putchar(buffer[i]);
i = i + 2;
continue;
}
putchar(buffer[i]);
}
putchar('\n');
return 0;
}
The problem statement doesn't require you to store the complete input in a buffer. The decision on what character to output only depends on the last two characters of input. Consider the following code:
#include <stdio.h>
int main(void)
{
// two variables for the last two input characters
int c = EOF, last = EOF;
while ((c = getchar()) != EOF)
{
// if both are a space, store a single '*' instead
if (c == ' ' && last == ' ')
{
c = '*';
last = EOF;
}
// print the output, and shift the buffer
if (last != EOF)
putchar(last);
last = c;
}
// take care of the last character in the buffer after we see EOF
if (last != EOF)
putchar(last);
}
no need for malloc and friends at all. This is a good expample for a problem that requires you to think carefully, before writing code, in order to not waste unnecessary resources on buffers.
Code for just printing:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char prev = EOF, curr;
while ((curr =(char)getchar()) != '\n' && curr != EOF)
{
if(curr==' '&&prev==' ')
{
curr = '*';
prev = EOF;
}
if (prev != EOF)
putchar(prev);
prev = curr;
}
putchar(prev);
return 0;
}
Using realloc for actually changing the string:
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned int len_max = 128;
char *m = malloc(len_max);
char c;
int counter= 0;
int i;
int current_size = 256;
printf("please input a string\n");
while ((c = getchar()) != '\n' && c != EOF)
{
m[counter] =(char)c;
counter++;
if(counter == current_size)
{
current_size = i+len_max;
m = realloc(m, current_size);
}
}
for(i=0; i<counter; i++)
{
if(m[i]== ' '&&m[i+1]==' ')
{
m[i]= '*';
putchar(m[i]);
i = i + 2;
continue;
}
putchar(m[i]);
}
putchar('\n');
free(m);
m = NULL;
return 0;
}
So I want to get all the lines from a file and turn them into a char* array. Problem is that whenever I try to append the character onto the end of the element it gives a segmentation fault.
char** loadOutputs(char *fileName, int *lineCount)
{
FILE *file = fopen(fileName, "r");
if (file) {
char c;
int lines = 0;
while ((c = fgetc(file)) != EOF)
if (c = '\n')
lines++;
rewind(file);
char **output = malloc(lines * sizeof(char*));
for (int i = 0; i < lines; i++)
output[i] = "";
int index = 0;
while ((c = fgetc(file)) != EOF)
if (c == '\n')
index++;
else
strcat(output[i], &c);
return output;
}
return NULL;
}
I always get a segmentation fault at strcat(output[i], &c);. I'd rather not create a fixed array size for the output because this could get fairly large and I don't want to use too much memory.
The following code:
for (int i = 0; i < lines; i++)
output[i] = "";
Is setting the pointer to an empty read only string.
You need to allocate some memory for the string:
I.e.
for (int i = 0; i < lines; i++) {
output[i] = malloc(MAX_LINE_LENGTH + 1);
}
Where MAX_LINE_LENGTH is some defined constant - perhaps #define MAX_LINE_LENGTH 100.
You will need to check that when reading the lines you do not exceed this length.
The following code will do this. This will resolve the other problem in that the address of c will not point to a null terminated string.
int index = 0;
int position = 0;
while ((c = fgetc(file)) != EOF) {
if (c == '\n') {
output[index][position] = 0; // Null terminate the line
position = 0; // Restart next line
index++;
} else {
if (position < MAX_LINE_LENGTH) { // Check if we have space!
output[index][position] = c; // Add character and move forward
position++;
}
}
}
output[index][position] = 0; // Add the null to the final line
Also you need to declare c as and int - i.e. change char c to int c. This is because EOF is outside the range for a char
I get weird values after reading from file (i should be max 100 but I get more), and if someone would explain when to use & * ** in pointers in a simple why couse my english is not very good when it comes to programing I would be grateful
This program should read words from file and if there is a number in the word change it to first letter of that word. If you have any suggestions on how I could change file reading I would also appreciate that. I am new to C (in school I did C++ but very basic levels)
# include <stdio.h>
# define MAX_LEN 100
int File_reading();
int main()
{char buffer;
File_reading();
}
int File_reading( )
{
FILE *stream;
char buffer[MAX_LEN + 1];
int i, ch;
stream = fopen("data.txt","r");
for (i = 0; (i < (MAX_LEN+1));i++)
{
if (((ch = fgetc(stream)) != EOF) && (ch != '\n'))
{
buffer[i] = ch;
}
}
buffer[i] = '\0';
if (fclose(stream))
perror("fclose error");
for (i=0;(i<(MAX_LEN+1));i++){
printf("%c \n", buffer[i]);
}
}
You're not stopping the loop when the file is over, and you're overstepping the array bound! That's terrible. Fix the loop, like this:
char buffer[MAX_LEN + 1];
size_t i;
for (i = 0; i != MAX_LEN; ++i)
{
int c = fgetc(stream);
if (c == EOF) { break; }
buffer[i] = c;
}
buffer[i] = '\0';