How do i use fgetc with gcc compiler - c

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

Related

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.

Remove a word from a sentence (string)

I am in the stage of preparing myself for exams, and the thing that I m least proud of are my skills with strings. What I need to do is remove a word from a sentence, without using <string.h> library at all.
This is what I've got so far. It keeps showing me that certain variables are not declared, such as start and end.
#include <stdio.h>
/* Side function to count the number of letters of the word we wish to remove */
int count(char *s) {
int counter = 0;
while (*s++) {
counter++;
s--;
return counter;
}
/* Function to remove a word from a sentence */
char *remove_word(const char *s1, const char *s2) {
int counter2 = 0;
/* We must remember where the string started */
const char *toReturn = s1;
/* Trigger for removing the word */
int found = 1;
/* First we need to find the word we wish to remove [Don't want to
use string.h library for anything associated with the task */
while (*s1 != '\0') {
const char *p = s1;
const char *q = s2;
if (*p == *q)
const char *start = p;
while (*p++ == *q++) {
counter2++;
if (*q != '\0' && counter2 < count(s2))
found = 0;
else {
const char *end = q;
}
}
/* Rewriting the end of a sentence to the beginning of the found word */
if (found) {
while (*start++ = *end++)
;
}
s1++;
}
return toReturn;
}
void insert(char niz[], int size) {
char character = getchar();
if (character == '\n')
character = getchar();
int i = 0;
while (i < size - 1 && character != '\n') {
array[i] = character;
i++;
character = getchar();
}
array[i] = '\0';
}
int main() {
char stringFirst[100];
char stringSecond[20];
printf("Type your text here: [NOT MORE THAN 100 CHARACTERS]\n");
insert(stringFirst, 100);
printf("\nInsert the word you wish to remove from your text.");
insert(stringSecond, 20);
printf("\nAfter removing the word, the text looks like this now: %s", stringFirst);
return 0;
}
your code is badly formed, i strongly suggest compiling with:
gcc -ansi -Wall -pedantic -Werror -D_DEBUG -g (or similar)
start with declaring your variables at the beginning of the function block, they are known only inside the block they are declared in.
your count function is buggy, missing a closing '}' (it doesn't compile)
should be something like
size_t Strlen(const char *s)
{
size_t size = 0;
for (; *s != '\n'; ++s, ++size)
{}
return size;
}
implementing memmove is much more efficient then copy char by char
I reformatted you code for small indentation problems and indeed indentation problems indicate real issues:
There is a missing } in count. It should read:
/* Side function to count the number of letters of the word we wish to remove */
int count(char *s) {
int counter = 0;
while (*s++) {
counter++;
}
return counter;
}
or better:
/* Side function to count the number of letters of the word we wish to remove */
int count(const char *s) {
const char *s0 = s;
while (*s++) {
continue;
}
return s - s0;
}
This function counts the number of bytes in the string, an almost exact clone of strlen except for the return type int instead of size_t. Note also that you do not actually use nor need this function.
Your function insert does not handle EOF gracefully and refuses an empty line. Why not read a line with fgets() and strip the newline manually:
char *input(char buf[], size_t size) {
size_t i;
if (!fgets(buf, size, stdin))
return NULL;
for (i = 0; buf[i]; i++) {
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
}
return buf;
}
In function remove_word, you should define start and end with a larger scope, typically the outer while loop's body. Furthermore s1 should have type char *, not const char *, as the phrase will be modified in place.
You should only increment p and q if the test succeeds and you should check that p and q are not both at the end of their strings.
last but not least: you do not call remove_word in the main function.
The complete code can be simplified into this:
#include <stdio.h>
/* Function to remove a word from a sentence */
char *remove_word(char *s1, const char *s2) {
if (*s2 != '\0') {
char *dst, *src, *p;
const char *q;
dst = src = s1;
while (*src != '\0') {
for (p = src, q = s2; *q != '\0' && *p == *q; p++, q++)
continue;
if (*q == '\0') {
src = p; /* the word was found, skip it */
} else {
*dst++ = *src++; /* otherwise, copy this character */
}
}
*dst = '\0'; /* put the null terminator if the string was shortened */
}
return s1;
}
char *input(char buf[], size_t size) {
size_t i;
if (!fgets(buf, size, stdin))
return NULL;
for (i = 0; buf[i]; i++) {
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
}
return buf;
}
int main() {
char stringFirst[102];
char stringSecond[22];
printf("Type your text here, up to 100 characters:\n");
if (!input(stringFirst, sizeof stringFirst))
return 1;
printf("\nInsert the word you wish to remove from your text: ");
if (!input(stringSecond, sizeof stringSecond))
return 1;
printf("\nAfter removing the word, the text looks like this now: %s\n",
remove_word(stringFirst, stringSecond));
return 0;
}
Your start and end pointers are defined within a block which makes their scope limited within that block. So, they are not visible to other parts of your code, and if you attempt to reference them outside their scope, the compiler will complain and throw an error. You should declare them at the beginning of the function block.
That said, consider the following approach to delete a word from a string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int delete_word(char *buf,
const char *word);
int main(void)
{
const char word_to_delete[] = "boy";
fputs("Enter string: ", stdout);
char buf[256];
fgets(buf, sizeof(buf), stdin);
if (delete_word(buf, word_to_delete))
{
printf("Word %s deleted from buf: ", word_to_delete);
puts(buf);
}
else
{
printf("Word %s not found in buf: ", word_to_delete);
puts(buf);
}
system("PAUSE");
return 0;
}
int chDelimit(int ch)
{
return
(ch == '\n' || ch == '\t') ||
(ch >= ' ' && ch <= '/') ||
(ch >= ':' && ch <= '#') ||
(ch >= '[' && ch <= '`') ||
(ch >= '{' && ch <= '~') ||
(ch == '\0');
}
char *find_pattern(char *buf,
const char *pattern)
{
size_t n = 0;
while (*buf)
{
while (buf[n] && pattern[n])
{
if (buf[n] != pattern[n])
{
break;
}
n++;
}
if (!pattern[n])
{
return buf;
}
else if (!*buf)
{
return NULL;
}
n = 0;
buf++;
}
return NULL;
}
char *find_word(char *buf,
const char *word)
{
char *ptr;
size_t wlen;
wlen = strlen(word);
ptr = find_pattern(buf, word);
if (!ptr)
{
return NULL;
}
else if (ptr == buf)
{
if (chDelimit(buf[wlen]))
{
return ptr;
}
}
else
{
if (chDelimit(ptr[-1]) &&
chDelimit(ptr[wlen]))
{
return ptr;
}
}
ptr += wlen;
ptr = find_pattern(ptr, word);
while (ptr)
{
if (chDelimit(ptr[-1]) &&
chDelimit(ptr[wlen]))
{
return ptr;
}
ptr += wlen;
ptr = find_pattern(ptr, word);
}
return NULL;
}
int delete_word(char *buf,
const char *word)
{
size_t n;
size_t wlen;
char *tmp;
char *ptr;
wlen = strlen(word);
ptr = find_word(buf, word);
if (!ptr)
{
return 0;
}
else
{
n = ptr - buf;
tmp = ptr + wlen;
}
ptr = find_word(tmp, word);
while (ptr)
{
while (tmp < ptr)
{
buf[n++] = *tmp++;
}
tmp = ptr + wlen;
ptr = find_word(tmp, word);
}
strcpy(buf + n, tmp);
return 1;
}
If you have to do it manually, just loop over the indicies of your string to find the first one that matches and than you’ll have a second loop that loops for all the others that matches and resets all and jumps to the next index of the first loop if not matched something in order to continue the searching. If I recall accuretaly, all strings in C are accesible just like arrays, you’ll have to figure it out how. Don’t afraid, those principles are easy! C is an easy langugae, thiught very long to write.
In order to remove: store the first part in an array, store the second part in an array, alloc a new space for both of them and concatinate them there.
Thanks, hit the upvote button.
Vitali
EDIT: use \0 to terminate your newly created string.

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 :)

caesar encryption in C with undefined input

iam trying to write a simple caesar program in C.
The input i want to give should be with undefined lenght like in the program.
The problem i have is, when i enter a short string like "HELLO WORLD" in the encrypted string i have some random additions at the end.
When i give a longer string as input the program crashes befor it starts to encrypt.
I have no idea where the problem could be, maybe some of you can give me a hand or have ideas what is crap here :/
Every advice is welcome thank you :)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// realloc the size of memory for the user input
char *inputString(FILE *fp, size_t size)
{
// the size is extendet by the input with the value of the provisional
char *str;
int ch = 0;
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);
}
// lowercase letters
void makeLowerCase(char *input)
{
while(*input != '\0') // "while(*input)" would also work
{
*input = tolower(*input);
input++;
}
}
// test function
// character length of the input
int lengthOfInput(char *input)
{
int len = 0;
while(*input != '\0') // "while(*input)" would also work
{
len++;
input++;
}
return len;
}
// encrypts the input caesar
char *encrypt(char *toBeEncrypted, int caesarNum)
{
int tmp = 0; // going through the input
char *tbE;
for(;*toBeEncrypted != '\0'; toBeEncrypted++, tmp++)
{
*(tbE+tmp) = *toBeEncrypted + caesarNum;
printf("%c", *(tbE+tmp));
}
return tbE;
}
// ------------------------------------------------------
// main
// ------------------------------------------------------
int main(void)
{
char *s; // input from user
char *encryptedString; // encrypted input/output
int loi = 0; // length of input
srand((unsigned)time(NULL)); // initialize random value for encryption
int caesar = (rand()%25) + 1; // random number for caesar encryption
printf("input string : ");
s = inputString(stdin, 10); // realloc the memory space for the input
makeLowerCase(s); // convert to lower case
printf("lower case: %s\n",s);
loi = lengthOfInput(s); // length of the input
printf("lenght of input: %d\n",loi);
printf("caesar number: %d\n",caesar);
encryptedString = encrypt(s, caesar); // encryption
printf("\nencrypted : %s",encryptedString); // output
free(s);
free(encryptedString); // free the memory
return 0;
}
You are using an uninitialized variable.
// encrypts the input caesar
char *encrypt(char *toBeEncrypted, int caesarNum)
{
int tmp = 0; // going through the input
char *tbE;
for(;*toBeEncrypted != '\0'; toBeEncrypted++, tmp++)
{
*(tbE+tmp) = *toBeEncrypted + caesarNum;
// ^
// ^ here tbE is used, but it has never been initialized
//
printf("%c", *(tbE+tmp));
}
return tbE;
}
There may be more issues.
Side note
In encrypt the loop should be written with array indexes rather than with pointer arithmetic for the sake of readability:
for(i = 0; toBeEncrypted[i] != '\0'; i++)
{
tbE[i] = toBeEncrypted[i] + caesarNum;
printf("%c", tbE[i]);
}

filling a Char array with scanf in C

How can I fill an empty Char Array with keyboard?
something like
char a_string[];
while("if not Q")
{
printf("Enter a number: ");
scanf("%c", a_string);
}
I know this is wrong
I just want to know how to give values to my a_string[], without limiting the size.
so the size will vary depend on how many keys i'm gonna enter from keyboard.
Thanks!
If you will know at the start of runtime how many keys you'll enter, you can have it ask first for the number of keys and then for the individual characters, as in the untested snippet below.
Otherwise, you have to set some real-world maximum (e.g. 10000) that will never be reached, or, if that's not possible, set a per-array maximum and make provisions for rollover into a new array. That last option really is the same (eventually bounded by memory) but gives you a larger maximum.
char *mychars;
int numchars;
printf("Please enter the total number of characters:\n");
if (scanf("%d", &numchars) == NULL) {
printf("couldn't read the input; exiting\n");
exit(EXIT_FAILURE);
}
if (numchars <= 0) {
printf("this input must be positive; exiting\n");
exit(EXIT_FAILURE);
}
mychars = (char *) malloc (numchars * sizeof(char));
int current_pos = 0;
printf("Enter a digit and hit return:\n");
while (scanf("%c", &mychars[current_pos]) != NULL && current_pos < numchars) {
current_pos++;
printf("Enter a digit and hit return:\n");
}
Try this:
#include <stdlib.h>
#include <stdio.h>
int main() {
char *string = NULL;
char *newstring = NULL;
char c = '\0';
unsigned int count = 0;
while(c != 'Q'){
c = getc(stdin);
if(string == NULL){
string = (char *) malloc(sizeof(char)); // remember to include stdlib.h
string[0] = c;
}
else{
newstring = (char *) realloc(string, sizeof(char)*count);
string = newstring;
string[count] = c;
}
count++;
}
string[count-1] = '\0'; // remove the Q character
fprintf(stderr,"here you are: %s",string);
free(string); // remember this!
return 0;
}
Repetitive calls to realloc() will meet the need.
Double realloc() size as needed to avoid O(n) calls.
char *GetQLessString(void) {
size_t size_alloc = 1;
size_t size_used = size_alloc;
char *a_string = malloc(size_alloc);
if (a_string == NULL) {
return NULL; // Out of memory
}
char ch;
while(scanf("%c", &ch) == 1 && (ch != 'Q')) {
size_used++;
if (size_used > size_alloc) {
if (size_alloc > SIZE_MAX/2) {
free(a_string);
return NULL; // Too big - been typing a long time
}
size_alloc *= 2;
char *new_str = realloc(a_string, size_alloc);
if (new_str == NULL) {
free(a_string);
return NULL; // Out of memory
}
a_string = new_str;
}
a_string[size_used - 2] = ch;
}
a_string[size_used - 1] = '\0';
return a_string;
}
Code could do a final realloc(a_string, size_used) to trim excess memory allocation.
Calling routine needs to call free() when done with the buffer.
The following would be cleaner.
int ch;
while((ch = fgetc(stdin)) != EOF && (ch != 'Q')) {

Resources