Multiple line input string using fgets - c

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;
}

Related

Read a line using Pointer variable in C

[Code]
#include <stdio.h>
//#include <conio.h> // getch()
int main(int argc, char *argv[])
{
char c, *s;
printf("Enter the number...\n");
while ((c=getchar()) != EOF && c != '\n' && c != '\t') {
putchar(c);
*s++ = c; // **What is wrong in here, the code is crashing!!**
}
printf("The number: %s\n", s);
return 0;
}
Output:
c:\works\workout\c>gcc tmp.c -o tmp
c:\works\workout\c>tmp
Enter the number...
434232
4
c:\works\workout\c>
Expected Output:
The actual given input number/string! (e.g 434232 in here)
Expecting output by using 'pointer' only (Without using 'scanf', 'char s[10]' etc.)
Thanks in advance!
First, you have to allocate s because it is a pointer.
Secondly, declare int c instead of char c because the definition of the functions getchar() and putchar() as:
int putchar(int c);
int getchar(void);
Finally, Use s[i] = ... instead of *s++ =.
The complete code (In this code, i use the realloc function for allocating each time you get new value from keyboard):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int c;
char *s = malloc(sizeof(char) + 1);
if (s == NULL)
exit(-1);
printf("Enter the number...\n");
int i = 0;
while ((c=getchar()) != EOF && c != '\n' && c != '\t') {
putchar(c);
s[i] = c;
// re-allocate because the size of s has to increase to store the new value
s = realloc(s, sizeof(char));
if (s == NULL)
exit(-1);
i++;
}
printf("The number: %s\n", s);
return 0;
}

Reading Multiple lines in 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.

Output not as expected

I am supposed to write a program to extract Web addresses starting with www. and ending with .edu. The program displays Web address contained in the input entered by the user. If the input does not contain a web address that starts with www. and ends with .edu, the program should display a message that indicates such a web address cannot be found.
Input: http://www.usf.edu/admission
Output: www.usf.edu
Input: https://www.facebook.com/
Output: Web address starting with www. and ending with .edu not found
However when my program runs, it is not displaying the correct output. I don't have any compiler errors or warnings so I'm not sure where the issue could be.
// This program extracts the text from the website URL
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define STR_LEN 1000
void read_line(char *str, int n);
void pass_check(char *str);
void extract(char *s1, char *s2);
int main(void)
{
char instr[STR_LEN + 1];
char outstr[STR_LEN + 1];
printf("Please enter a URL: ");
read_line(instr, STR_LEN);
extract(instr, outstr);
puts(outstr);
pass_check(outstr);
return 0;
}
void extract(char *s1, char *s2) {
char *p, *q;
q = s2;
for (p = s1 + 7; *p != 0; p++) {
if (*p == '/')
break;
else {
*q = *p;
q++;
}
}
*q = '\0';
*p = '\0';
}
void read_line(char *str, int n) {
int ch;
int i = 0;
while ((ch = getchar()) != '\n') {
if (i < n) {
*str++ = ch;
i++;
}
}
*str = '\0';
}
void pass_check(char *str) {
const char *fref = "www";
const char *lref = "edu";
int len = strlen(str);
printf("%d", len);
char *l = &str[len - 3];
char f[STR_LEN + 1];
strncpy(f, str, 3);
if ((strcmp(f, fref) == 0) && strcmp(l, lref) == 0) {
printf("Output: ");
puts(str);
printf("\n");
} else
printf("Please only insert a .edu URL.");
}
The function strncpy() does not do what you think it does: strncpy(f, str, 3); will not append a null byte to f, so strcmp(f, fref); will actually have undefined behavior as f is uninitialized beyond the first 3 bytes.
Do not use this function, learn why from these blogs:
https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/
https://blog.liw.fi/posts/strncpy/
Also note that your readline() function will run an infinite loop is the file is empty or not terminated by a newline.
Here is a corrected version:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define STR_LEN 1000
void read_line(char *str, size_t n);
int extract(const char *str, char *dest);
int main(void) {
char instr[STR_LEN + 1];
char outstr[STR_LEN + 1];
printf("Please enter a URL: ");
read_line(instr, sizeof(instr));
if (extract(instr, outstr)) {
puts(outstr);
} else {
printf("Web address starting with www. and ending with .edu not found\n");
}
return 0;
}
int read_line(char *str, size size) {
int ch;
size_t i = 0;
while ((ch = getchar()) != EOF && c != '\n') {
if (i + 1 < size) {
str[i++] = ch;
}
}
str[i] = '\0';
return (ch == EOF && i == 0) ? EOF : i;
}
int extact(const char *str, char *dest) {
const char *p;
*dest = '\0';
for (;;) {
if ((p = strstr(str, "https://www.")) != NULL) {
p += 8; // skip the https:// prefix
} else
if ((p = strstr(str, "http://www.")) != NULL) {
p += 7; // skip the http:// prefix
} else {
break;
}
// URL starts with www.
size_t len = strcspn(p, "/ \n"); // compute length of website name
if (len > 8 && !memcmp(p + len - 4, ".edu", 4)) {
// copy website name, assuming dest is at least as large as str
strncat(dest, p, len);
return 1;
}
str = p + len;
}
return 0;
}

strcat is giving me a segmentation fault error

After verifying that strcat is where the error occurs, I then check the previous example in my assignment. In my previous examples I use strcat(actually strncat) in the same fashion as I do for my following code. I am not too sure.
The purpose of my program is to loop through "string" and remove any occurances the character 'c' from string.
main.c:
char string[100]={0}, c[3];
printf("Enter a String: ");
fgets(string, 100, stdin);
if (string[98] == '\n' && string[99] == '\0') { while ( (ch = fgetc(stdin)) != EOF && ch != '\n'); }
printf("Enter a Char: ");
fgets(c, 2, stdin);
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
rmchr(string, c[0]);
header:
rmchr(char *string, char c)
{
int i=0;
char *word[100];
int s = strlen(string);
for(i=0; i<=(s-2); i++)
{
if(string[i] != c)
{
strcat(word, string[i]);
}
}
}
char *word[100];
It will hold a string in your program so use:
char word[100];
that is, an array of char instead of an array of char *.
Then strcat concatenates to a string but word is not initialized. Make it a string with:
word[0] = '\0';
Then string[i] is a character but strcat needs pointers to character arguments: to use a pointer use &string[i].
Finally the problem in your rmchr function is it has to return something, either through the arguments or via a return statement but it doesn't.
There are more than one point to mention here, like
rmchr() definition should have a return type, maybe void if you're not returning anything.
[FWIW, In that case, I wounder, how you'll make use of the local variable word]
inside rmchr(), word needs to be an array of chars, not char pointers. You need to change char * word[100] to char word[100].
In strcat(), both the arguments, needs to be a pointer. You need to use &string[i], in that case.
The following seems to compile fine but your code doesnt do quite what you said you wanted, "The purpose of my program is to loop through "string" and remove any occurances the character 'c' from string.". the function doesn't remove the character or return a copy of the string with the character excluded. I wrote a function that copies the string after removing the character and returns pointer to it. below is your code a bit modified and under it is my function
//Just a compilable version of your code, not sure if it does what u want
#include <stdio.h>
#include <string.h>
void rmchr(char *string, char c)
{
int i=0;
char word[100];
int s = (int)strlen(string);
for(i=0; i<=(s-2); i++)
{
if(string[i] != c)
{
strcat(word, (char *)(&string[i]));
}
}
}
int main(int argc, const char * argv[]) {
char string[100] = {0}, c[3];
char ch;
printf("Enter a String: ");
fgets(string, 100, stdin);
if (string[98] == '\n' && string[99] == '\0') {
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
}
printf("Enter a Char: ");
fgets(c, 2, stdin);
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
rmchr(string, c[0]);
return 0;
}
There you go, with a demo main
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* rmchr(char *string, char ch)
{
int counter = 0;
int new_size = 0;
char corrected_string[100];
while (string[counter] != '\n' && string[counter] != '\0' && string[counter] != EOF) {
if (string[counter] != ch) {
corrected_string[new_size] = string[counter];
new_size++;
}
counter++;
}
char *new_string = (char *)malloc((new_size+1) * sizeof(char));
for (int j = 0; j <= new_size; j++) {
new_string[j] = corrected_string[j];
}
return new_string;
}
int main(int argc, const char * argv[]) {
char *s = "The char 'c' will be removed";
char *new = rmchr(s, 'c');
printf("%s", new);
return 0;
}

Program counting words c

I got a almost good working program to count words from standard input.
The word what has to be count is a program argument.
The problem is that I use a white space to see a word but I also must count within th word itself.
Example: if my input is aa aaaa #EOF, and I want to count aa the result should be 4. My code result 2.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int word_cnt(const char *s, char *argv[])
{
int cnt = 0;
while(*s != '\0')
{
while(isspace(*s))
++s;
if(*s != '\0')
{
if(strncmp(s, argv[1], strlen(argv[1])) == 0)
++cnt;
while(!isspace(*s) && *s != '\0')
++s;
}
}
return cnt;
}
int main(int argc, char *argv[])
{
char buf[1026] = {'\0'};
char *p="#EOF\n";
int tellen = 0;
if (argc != 2)
{
printf("Kan het programma niet uitvoeren, er is geen programma argument gevonden\n");
exit(0);
}
while((strcmp(buf, p) !=0))
{
fgets (buf, 1025, stdin);
tellen += word_cnt(buf, argv);
}
printf("%d", tellen);
return 0;
}
Where you have this:
if(strncmp(s, argv[1], strlen(argv[1])) == 0)
++cnt;
while(!isspace(*s) && *s != '\0')
++s;
Try this:
/* if it matches, count and skip over it */
while (strncmp(s, argv[1], strlen(argv[1])) == 0) {
++cnt;
s += strlen(argv[1]);
}
/* if it no longer matches, skip only one character */
++s;
int word_cnt(const char *s, char *argv[])
{
int cnt = 0;
int len = strlen(argv[1]);
while(*s)
{
if(strncmp(s, argv[1], len) == 0)
++cnt;
++s;
}
return cnt;
}
Try strncmp() in a loop.
/* UNTESTED */
unsigned wc(const char *input, const char *word) {
unsigned count = 0;
while (*input) {
if (strncmp(input, word, strlen(word)) == 0) count++;
input++;
}
return count;
}

Resources