Reading Multiple lines in C - c

So I am trying to read input from a text file and print the exact same thing I read in C.So this below is the input followed by enter:
input: Hi
output: Hi
#include <stdio.h>
#include <stdlib.h>
char *inputString(FILE *fp, size_t size) {
//The size is extended by the input with the value of the provisional
char *str;
int ch;
size_t len = 0;
str = realloc(NULL, sizeof(char) * size); //size is start size
if (!str)
return str;
while (EOF != (ch = fgetc(fp)) && ch != '\n') {
str[len++] = ch;
if (len == size) {
str = realloc(str, sizeof(char) * (size += 16));
if (!str)
return str;
}
}
str[len++] = '\0';
return realloc(str, sizeof(char) * len);
}
int main(void) {
char *m;
// printf("input string : ");
m = inputString(stdin, 10);
printf("%s\n", m);
free(m);
return 0;
}
For this input:
Hi, this is the first line
This is the second line
This is the third line \n
This is the output I expected:
Hi, this is the first line
This is the second line
This is the third line \n
This is what I got:
Hi, this is the first line
It makes sense that the code is printing only the first line, but since the condition in the guard will no longer be true after hitting the new line, but I don't know how to structure my code so it reads line by line and prints them respectively.

If you want the code to read each line, remove && ch != '\n' from the condition of the while loop.
Also, the code is reading from stdin instead of a file. Use fopen to read from a file, i.e. m = inputString(fopen("filename.txt", "r"), 512).

Try this,
#include<stdio.h>
void main(int argc, char **argv)
{
int cnt=0;
char buf[1024];
FILE *fptr=stdin;
printf("Input: \n");
char ch=fgetc(fptr);
buf[cnt++]=ch;
while(ch!='$')
{
buf[cnt++]=ch;
ch=fgetc(fptr);
}
buf[cnt++]='$';
buf[cnt]='\0';
printf("Output:\n");
fputs(buf,stdout);
fclose(fptr);
}
I have put '$' as the delimiter.
I have used an extra buffer as newline is bound to EOF for stdin. So if I print out the character immediately it comes out of loop.

All you need is repeat the process as long as you can read lines:
int main(void) {
char *m;
// printf("input strings: ");
while ((m = inputString(stdin, 10)) != NULL) {
printf("%s\n", m);
free(m);
}
return 0;
}
For this to work correctly, you must return NULL at end of file:
#include <stdio.h>
#include <stdlib.h>
char *inputString(FILE *fp, size_t size) {
//The size is extended by the input with the value of the provisional
int ch;
size_t len = 0;
char *str = malloc(size);
if (str == NULL)
return NULL;
while ((ch = fgetc(fp)) != EOF && c != '\n') {
if (len + 2 > size) {
char *new_str = realloc(str, size += 16);
if (!new_str) {
free(str);
return NULL;
str = new_str;
}
str[len++] = ch;
}
if (c == EOF && len == 0) {
/* at end of file */
free(str);
return NULL;
}
str[len++] = '\0';
return realloc(str, len);
}

Instead of:
while(EOF!=(ch=fgetc(fp))&& ch != '\n' ){
// stuff
}
you could do:
while(EOF!=(ch=fgetc(fp))){
// stuff
if (ch == '\n') break;
}
Now you have consumed the newline.

Related

Segmentation Fault when finding longest word in input

I have written a program to find the longest word in the input. I get no errors when using valgrind or running tests locally, but the grading program I email the code to reports a segmentation fault.
int main(void)
{
char *longest = malloc(1);
size_t size = 1;
do {
char word[20];
if (scanf("%s", word) > 0) {
if (strlen(word) > size) {
longest = realloc(longest,strlen(word)+1);
strcpy(longest,word);
size = strlen(word);
}
}
} while (getchar() != EOF);
printf("%zu characters in longest word: %s\n", strlen(longest),longest);
free(longest);
return 0;
}
Your problem is in the line char word[20]; and the way scanf reads words. From scanf's point of view, a word is any sequence of non-spaces. For example, realloc(longest,strlen(word)+1); is treated as one word, and that alone is longer than 20 characters.
You should use a more robust function to read words and allocate space for them. The most cost-efficient solution is getline() for reading the line followed by strsep() for extracting words.
Without relying on the luxurities of POSIX-functions, only standard-C for variable word-length:
#include <assert.h> // assert()
#include <stddef.h> // size_t
#include <stdbool.h> // bool, true, false
#include <stdlib.h> // EXIT_FAILURE, realloc(), free()
#include <stdio.h> // fscanf(), fgetc(), ungetc(), printf(), fputs()
#include <ctype.h> // isspace()
#include <string.h> // strlen(), strcat(), strcpy()
#define WORD_BUFFER_SIZE 20
#define STRING(value) #value
#define STRINGIFY(value) STRING(value)
// reads and discards whitespace, returns false on EOF
bool skip_ws(FILE *stream)
{
int ch;
while ((ch = fgetc(stream)) != EOF && isspace(ch));
if(!isspace(ch) && ch != EOF) // if it was not whitespace and not EOF
ungetc(ch, stream); // pretend we were never here.
return ch != EOF;
}
bool read_word(char **dst, FILE *stream)
{
assert(dst);
char chunk_buffer[WORD_BUFFER_SIZE + 1];
if (!skip_ws(stream)) // if we encounter EOF before any other non-whitespace
return false;
// read chunk by chunk
for (size_t i = 0; fscanf(stream, "%" STRINGIFY(WORD_BUFFER_SIZE) "s", chunk_buffer) == 1; ++i)
{
size_t chunk_length = strlen(chunk_buffer);
// adjust *dst's size
char *tmp = realloc(*dst, (i * WORD_BUFFER_SIZE + chunk_length + 1) * sizeof(*tmp));
if (!tmp) {
free(*dst);
*dst = NULL;
return false;
}
*dst = tmp;
if (i == 0) // zero terminate it if it is the first junk
**dst = '\0'; // for strcat() to behave well.
strcat(*dst, chunk_buffer); // add the current chunk to *dst.
int next_char = fgetc(stream);
ungetc(next_char, stream);
if (chunk_length < WORD_BUFFER_SIZE || isspace(next_char) || next_char == EOF)
return true;
}
return true;
}
int main(void)
{
char *word = NULL;
char *longest_word = NULL;
size_t longest_length = 0;
while (read_word(&word, stdin)) {
size_t length = strlen(word);
if (length > longest_length) {
char *tmp = realloc(longest_word, (length + 1) * sizeof *tmp);
if (!tmp) {
fputs("Not enough memory. :(\n\n", stderr);
free(longest_word);
free(word);
return EXIT_FAILURE;
}
longest_length = length;
longest_word = tmp;
strcpy(longest_word, word);
}
}
free(word);
printf("%zu characters in the longest word: \"%s\"\n\n", longest_length, longest_word);
free(longest_word);
}

reading and saving known number of lines of unknown lengths of strings

I want to receive the number of lines of input from the user then read and save the lines of unknown lengths in an array.
I know that the way I am saving the lines is wrong but I don't know how to correct it.
int nos; // number of strings
scanf_s("%d", &nos);
char** strs = malloc(nos * sizeof(char*)); // array of strings
for (int i = 0; i < nos; i++) // receiving strings
{
scanf_s("%s", (strs+i));
}
You're close, but you're forgetting to allocate memory for the string. If you're working with POSIX-compliant systems (i.e. pretty much everything except Windows) then use the %ms scanf() format specifier to allocate the buffer for the string as you're reading it (note that this stops after whitespace):
scanf("%ms", &strs[i]);
For Windows, implement a gets()-like function:
#include <stdlib.h>
#include <stdio.h>
int msgets(char **str)
{
int ch = 0;
size_t len = 0;
while(ch != '\n')
{
len++;
*str = realloc(*str, len);
ch = getchar();
(*str)[len-1] = ch;
}
(*str)[--len] = 0;
return len;
}
Here's how to use it in replacement of the scanf() line:
msgets(&strs[i]);
Other than that, your code looks fine.
Here's an almost complete example with my code included:
#include <stdlib.h>
#include <stdio.h>
int msgets(char **str)
{
int ch = 0;
size_t len = 0;
while(ch != '\n')
{
len++;
*str = realloc(*str, len);
ch = getchar();
(*str)[len-1] = ch;
}
(*str)[--len] = 0;
return len;
}
int main(void)
{
int nos; // number of strings
scanf("%d ", &nos);
char** strs = malloc(nos * sizeof(char*)); // array of strings
for (int i = 0; i < nos; i++) // receiving strings
{
msgets(&strs[i]);
}
/* Do something with strs[] here */
return 0;
}
if you read carefully this answerHow can I read an input string of unknown length? , and modify your code it should be something like this.
I also add a print for loop to see the results of this code
#include <stdio.h>
#include <stdlib.h>
char *inputString(FILE* fp, size_t size){
char *str=NULL;
int ch;
size_t len = 0;
str = realloc(str, sizeof(char)*size);
if(!str){
printf("[DEBUG]\n");
return str;
}
while(EOF!=(ch=fgetc(fp)) && ch != '\n'){
str[len++]=ch;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return str;
}
}
str[len++]='\0';
return realloc(str, sizeof(char)*len);
}
void empty_stdin (void) /* simple helper-function to empty stdin */
{
char c;
while ((c = getchar()) != '\n' && c != EOF);
return;
}
int main(void){
int nos,i; /*number of strings*/
scanf("%d", &nos);
empty_stdin();
char ** strs = malloc(nos * sizeof(char*)); /*array of strings*/
for (i = 0; i < nos; i++) {/*receiving strings*/
*(strs+i) = inputString(stdin,1);
}
for(i=0;i<nos;i++){
printf("%s\n",*(strs+i));
}
return 0;
}
input:
3
123456789
foo
hello world
output:
123456789
foo
hello world

can anyone explain me how does this function work?

I don't understand what this function do. Can anyone explain me in detail please?
char *my_getline(FILE *stream) {
char *line = NULL;
size_t pos = 0;
int c;
while ((c = getc(stream)) != EOF) {
char *newp = realloc(line, pos + 2);
if (newp == NULL) {
free(line);
return NULL;
}
line = newp;
if (c == '\n')
break;
line[pos++] = (char)c;
}
if (line) {
line[pos] = '\0';
}
return line;
}
If you can add a comment on my code, I think that will help me. I want to search a substring in a string and I found this function code.
This is the main function:
int main(void) {
char *str, *sub;
size_t len1, len2, i, count = 0;
printf("Insert string :\n");
str = my_getline(stdin);
printf("insert substring :\n");
sub = my_getline(stdin);
if (str && sub) {
len1 = strlen(str);
len2 = strlen(sub);
for (i = 0; i + len2 <= len1; i++) {
if (!memcmp(str + i, sub, len2)) {
count++;
printf("Substring found at index : %d\n", i);
}
}
printf("in the number of: %d\n", count);
if (count == 0) {
printf("Substring not found\n");
}
}
free(str);
free(sub);
return 0;
}
I understand the main function but unable to understand the logic in function my_getline.
Please help me in understanding the logic. Thanks!
char *my_getline(FILE *stream) {
// pointer to the line to be read:
char *line = NULL;
// position of the next character:
size_t pos = 0;
// single character:
int c;
while ((c = getc(stream)) != EOF) { // read 1 character at a time until EOF
// allocate a new buffer with room for the char just read + a 0 terminator
// when `line` is NULL, this is the same as `malloc()`, otherwise it
// will change the size of the allocation:
char *newp = realloc(line, pos + 2);
// check for errors:
if (newp == NULL) {
free(line);
return NULL;
}
// no errors, assign new buffer to `line`:
line = newp;
// end of line found: we're done:
if (c == '\n')
break;
// otherwise add new character to the line:
line[pos++] = (char)c;
}
// if there was *anything* to read, add 0 terminator (marks end of string):
if (line) {
line[pos] = '\0';
}
return line;
}
That's about it. Note it's horribly inefficient for two reasons: It reads only one character at a time and it calls realloc() for each and every character.
A better solution would use e.g. fgets() and increase the buffer size in reasonable chunks, for example like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GETLINE_CHUNK 1024
static void xrealloc(void *bufPtr, size_t size)
{
void **buf = bufPtr;
void *tmp = realloc(*buf, size);
if (!tmp)
{
free(*buf);
*buf = 0;
}
*buf = tmp;
}
char *my_getline(FILE *stream)
{
// allocate first chunk:
char *buf = malloc(GETLINE_CHUNK);
if (!buf) return 0;
*buf = 0;
size_t pos = 0;
// read up to GETLINE_CHUNK bytes, until newline:
while (fgets(buf + pos, GETLINE_CHUNK, stream))
{
// look for newline:
char *nlPos = strchr(buf, '\n');
if (nlPos)
{
// found, then our line is complete
*nlPos = 0;
// shrink buffer to needed size
xrealloc(&buf, nlPos-buf+1);
return buf;
}
// set next offset to read
pos = strlen(buf);
// increase buffer size to have room for a whole other GETLINE_CHUNK:
xrealloc(&buf, pos + GETLINE_CHUNK);
if (!buf) return 0;
}
// if nothing was read, free buffer and return NULL:
if (*buf == 0)
{
free(buf);
buf = 0;
}
return buf;
}
int main(void)
{
char *line = my_getline(stdin);
if (line)
{
puts(line);
free(line);
}
else puts("no input!");
return 0;
}
Well this function gives you line, Lets go Step by Step:
char *my_getline(FILE *stream) {
char *line = NULL; //this is just pointer initialization
size_t pos = 0; //position variable definition and init
int c; //a variable to store temporary character
while ((c = getc(stream)) != EOF) //read every character till end of file
{
// To dynamically allocate memory, with reference to the
// number of character and plus '2' is just to compensate null
// character and the character(Since pos is 0)
char *newp = realloc(line, pos + 2);
if (newp == NULL) { // this is to check whether memory was alloacted properly or not.
free(line); //if not free line
return NULL;// break the program and return NULL
}
line = newp;// if memory is allocated properly store allocated memory in line pointer
if (c == '\n') //if new line is detected
break;// break the while loop
line[pos++] = (char)c; // store the character in dynamically allocated memory and new character in new location.
}
if (line) { //if line contains something then add a null character at last, to complete that string
line[pos] = '\0';
}
return line; //returns the content of line.
}
Hope this helps :)

How do i use fgetc with gcc compiler

I am trying to get 2 inputs from a user:
the first one is a size which i get using scanf.
the next input is a string of unknown size,
and the problem is that the first char on the input is the "enter" the user pressed from the line before therefor i dont get an input at all.
I will just note that on visual studio its completely fine! the problem is only on my mac and on my friends linux.
here is the code:
int main()
{
int size;
char* inputString;
printf("Enter the number of computers:");
scanf("%d", &size);
if (size == 1)
{
printf("Only one computer\n");
return;
}
inputString = malloc(stringSize);
inputString = inputStrings(stdin, stringSize);
}
char *inputStrings(FILE* fp, int size)
{
//The size is extended by the input with the value of the provisional
char *str;
int ch = 0;
int len = 0;
str = realloc(NULL, sizeof(char)*size);//size is start size
if (!str)return str;
while (EOF != (ch = fgetc(fp)) && ch != '\n')
{
str[len++] = ch;
if (len == size)
{
str = realloc(str, sizeof(char)*(size += 16));
if (!str)return str;
}
}
str[len++] = '\0';
return realloc(str, sizeof(char)*len);
}

Multiple line input string using fgets

I want to input a multiple-line string using:
fgets(str,100,stdin)
and then output the same string.
For example:
Input:
my name is sandy
i am learning C
and the output should be:
my name is sandy
i am learning C
#include <stdio.h>
#include <string.h>
char *mfgets(char * restrict s, int n, FILE * restrict stream){
int ch, i=0;
if(n<1)return NULL;
if(n==1){
*s = '\0';
return s;
}
while(EOF!=(ch=fgetc(stream))){
s[i++] = ch;
if(i == n - 1) break;
if(ch == '\n'){
char next = fgetc(stream);
if(next == '\n')
break;
else
ungetc(next, stream);
}
}
s[i] = '\0';
return i == 0 ? NULL : s;
}
int main(int argc, char *argv[]){
char str[100];
printf("input (only newline is end)\n");
mfgets(str, 100, stdin);
printf("%s", str);
return 0;
}

Resources