I have a problem, they gave me a task. They told us that we must use a pointer to put the value from the keyboard to array and then print that array.
I try to create that, but I don't know why this is wrong. I define my array then I get value and put that value into an array.
#include <stdio.h>
#include <stdlib.h>
#define N 10000 // Maximum array size
int main ()
{
char keyboardArray[N];
char *r;
r = keyboardArray;
while( (*r++ = getchar()) != EOF );
printf("You write %s", r);
return 0;
}
You have several problems:
At the end of the loop, r points to the end of the string, not the beginning. So printing r won't print the string that was entered. You should print the keyboardArray rather than r.
You're never adding a null terminator to the string, so you can't use the %s format operator.
getchar() returns int, not char -- this is needed to be able to distinguish EOF from ordinary characters. So you need to read into a different variable before storing into the array.
int main ()
{
char keyboardArray[N];
char *r;
int c;
r = keyboardArray;
while( (c = getchar()) != EOF ) {
*r++ = c;
}
*r = '\0'; // Add null terminator
printf("You write %s\n", keyboardArray);
}
Note that this will read until EOF, so the user will have to type a special character like Control-d (on Unix) or Control-z (on Windows) to end the input. You might want to check for newline as well, so they can enter a single line:
while ((c = getchar()) != EOF && c != '\n') {
I think that in any case you need an intermediate variable that will accept a read character.
Also you need to append the entered sequence of characters with the terminating zero.
For example
#include <stdio.h>
#define N 10000 // Maximum array size
int main( void )
{
char keyboardArray[N];
char *r = keyboardArray;
for ( int c;
r + 1 < keyboardArray + N && ( c = getchar() ) != EOF && c != '\n';
++r )
{
*r = c;
}
*r = '\0';
printf( "You write %s\n", keyboardArray );
}
Related
I am writing a program to read a user input statement and extract all integers from the input. For example, if I enter "h3ll0", the program will output "30". I have used the fgets function to read the user input.
However, I am currently reading about getchar() and would like to know what would be the best way to use getchar() in my program to read user input instead of fgets. I am not really clear on how getchar() works and what situations it can be useful in.
This question is related to a project that specifically asks for getchar() as the method of reading user input. As I was unclear on how getchar() works, I built the rest of the program using fgets to ensure it was working.
#include <stdio.h>
int main()
{
char user_input[100];
int i;
int j = 0;
printf("Please enter your string: ");
fgets(user_input ,100, stdin);
for(i = 0; user_input[i] ; i++)
{
if(user_input[i] >= '0' && user_input[i] <= '9')
{
user_input[j] = user_input[i];
j++;
}
}
user_input[j] = '\0';
printf("Your output of only integers is: ");
printf("%s\n", user_input);
return 0;
}
OP: unclear on how getchar() works
int fgetc(FILE *stream) typically returns 1 of 257 different values.
"If ... a next character is present, the fgetc function obtains that character as an unsigned char converted to an int C11 §7.21.7.1 2
On end-of-file or input error (rare), EOF, is returned.
OP: to use getchar() in my program to read user input instead of fgets.
Create your own my_fgets() with the same function signature and same function as fgets() and then replace.
char *fgets(char * restrict s, int n, FILE * restrict stream);
The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array. C11 §7.21.7.2 2
Return the same value
The fgets function returns s if successful. If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned. If a read error occurs during the operation, the array contents are indeterminate and a null pointer is returned. §7.21.7.2 3
Sample untested code
#include <stdbool.h>
#include <stdio.h>
char *my_fgets(char * restrict s, int n, FILE * restrict stream) {
bool something_read = false;
int ch = 0;
char *dest = s;
// Room ("reads at most one less") and EOF not returned?
while (n > 1 && (ch = fgetc(stream)) != EOF) {
n--;
something_read = true;
*dest++ = (char) ch;
if (ch == '\n') {
break; // "No additional characters are read after a new-line character"
}
}
// Did code end the while loop due to EOF?
if (ch == EOF) {
// Was EOF due to end-of-file or rare input error?
if (feof(stream)) {
// "If end-of-file is encountered and no characters ... read into the array ..."
if (!something_read) {
return NULL;
}
} else {
// "If a read error ..."
return NULL; // ** Note 1
}
}
// room for \0?
if (n > 0) {
*dest = '\0'; //" A null character is written immediately after the last character"
}
return s;
}
Perhaps improve fgets() and use size_t for n.
char *my_fgets(char * restrict s, size_t n, FILE * restrict stream);
fgets() with n <= 0 is not clearly defined. Using size_t, an unsigned type, at least eliminates n < 0 concerns.
Note 1: or use s = NULL; instead of return NULL; and let the remaining code null terminate the buffer. We have that option as "array contents are indeterminate".
Something like this should work as a clunky replacement to fgets using only getchar. I don't guarantee the accuracy of the error handling.
I don't think you would ever want to use getchar over fgets in an application. Getchar is more limited and less secure.
#include <stdint.h>
void your_fgets(char *buffer, size_t buffer_size)
{
int i;
size_t j;
if (buffer_size == 0)
return ;
else if (buffer_size == 1)
{
buffer[0] = '\0';
return ;
}
j = 0;
while ((i = getchar()) != EOF)
{
buffer[j++] = i;
if (j == buffer_size - 1 || i == '\n')
{
buffer[j] = '\0';
return ;
}
}
buffer[j] = '\0';
}
I am baffled by the comments on this post suggesting that fgets is easier to use. Using fgets unnecessarily complicates the issue. Just do:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int
main(int argc, char **argv)
{
int c;
while( ( c = getchar() ) != EOF ) {
if(isdigit(c) && (putchar(c) == EOF)) {
perror("stdout");
return EXIT_FAILURE;
}
}
return ferror(stdin);
}
There is absolutely no reason to use any additional buffering, or read the input one line at a time. Maybe you'll want to output newlines as they come in, but that would be an implementation detail that is left unspecified in the question. Either way, it's utterly trivial (if(( c == '\n' || isdigit(c)) && (putchar(c) == EOF))). Just read a character and decide if you want to output it. The logic is much easier if you don't think about the input as being more complicated than it is. (It's not line-oriented...it's just a stream of bytes.)
If, for some unknown reason you want to make this tool usable only in an interactive setting and load up your output with excess verbosity, you can easily do something like:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int
main(int argc, char **argv)
{
int c;
do {
int want_header = 1;
printf("Please enter your string: ");
while( ( c = getchar() ) != EOF && c != '\n' ) {
if(! isdigit(c)) {
continue;
}
if(want_header) {
want_header=0;
printf("Your output of only integers is: ");
}
if(putchar(c) == EOF) {
perror("stdout");
return EXIT_FAILURE;
}
}
if( c == '\n')
putchar(c);
want_header = 0;
} while(c == '\n');
return ferror(stdin);
}
but, please, don't do that. (Imagine if grep started by emitting a prompt that said "please enter the regex you would like to search for"!)
I am making a simple program to read from a file character by character, puts them into tmp and then puts tmp in input[i]. However, the program saves a character in tmp and then saves the next character in input[i]. How do I make it not skip that first character?
I've tried to read into input[i] right away but then I wasn't able to check for EOF flag.
FILE * file = fopen("input.txt", "r");
char tmp;
char input[5];
tmp= getc(file);
input[0]= tmp;
int i=0;
while((tmp != ' ') && (tmp != '\n') && (tmp != EOF)){
tmp= getc(file);
input[i]=tmp;
length++;
i++;
}
printf("%s",input);
It's supposed to print "ADD $02", but instead it prints "DD 02".
You are doing things in the wrong order in your code: The way your code is structures, reading and storing the first char is moved out of the loop. In the loop, that char is then overwritten. In that case start with i = 1.
Perhaps you want to read the first character anyway, but I guess you want to read everything up to the first space, which might be the first character. Then do this:
#include <stdio.h>
int main(void)
{
char input[80];
int i = 0;
int c = getchar();
while (c != ' ' && c != '\n' && c != EOF) {
if (i + 1 < sizeof(input)) { // store char if the is room
input[i++] = c;
}
c = getchar();
}
input[i] = '\0'; // null-terminate input
puts(input);
return 0;
}
Things to note:
The first character is read before the loop. the loop condition and the code that stores the char then use that char. Just before the end of the loop body, the next char is read, which will then be processed in the next iteration.
You don't enforce that the char buffer input cannot be overwritten. This is dangerous, especially since your buffer is tiny.
When you construct strings char by char, you should null-terminate it by placing an explicit '\0' at the end. You have to make sure that there is space for that terminator. Nearly all system functions like puts or printf("%s", ...) expect the string to be null-terminated.
Make the result of getchar an int, so that you can distinguish between all valid character codes and the special value EOF.
The code above is useful if the first and subsequent calls to get the next item are different, for example when tokenizing a string with strtok. Here, you can also choose another approach:
while (1) { // "infinite loop"
int c = getchar(); // read a char first thing in a loop
if (c == ' ' || c == '\n' || c == EOF) break;
// explicit break when done
if (i + 1 < sizeof(input)) {
input[i++] = c;
}
}
This approach has the logic of processing the chars in the loop body only, but you must wrap it in an infinite loop and then use the explicit break.
I'm new to C, I have been asked to make a program in C asking to print each letter after a '.' after a user has entered an input.
For example if the user enters a..bcd..e.f..gh the output should be befg
which is the exact example I have been given in class.
I assume this would need to use pointers but I am unsure how to deal with this question, here is what I have tried to do so far. I know it is not correct, please help me understand how to use pointers to deal with this question.
#include <stdio.h>
int main() {
char *c, count =0;
printf("enter some characters");
scanf("%s", &c);
while( c != EOF ) {
if (c != '.') {
count ++;
}
else; {
printf("%s", c);
}
}
}
The program can look the following way
#include <stdio.h>
#define N 100
int main( void )
{
char s[N];
const char DOT = '.';
printf( "Enter some characters: " );
fgets( s, N, stdin );
for ( char *p = s; *p; ++p )
{
if ( p[0] == DOT && p[1] != DOT ) putchar( p[1] );
}
putchar( '\n' );
}
Its output might look like
Enter some characters: a..bcd..e.f..gh
befg
Take into account that here any symbol after a dot (except the dot itself) is printed. You can add a check that there is a letter after a dot.
You don't really need pointers for this, or even an array. Basically it's a simple state engine: read each character, if '.' is encountered, set a flag so the next character is printed.
#include <stdio.h>
int main() {
int c, flag = 0;
while ((c = getchar()) != EOF) {
if (c == '.')
flag = 1;
else if (flag) {
putchar(c);
flag = 0;
}
}
return 0;
}
There are some errors in your code:
- char* c means a pointer to one or more characters.
But where does it point to?
- scanf reads a string up to an "white space". White space characters are the space itself, a newline, a tab character or an EOF. scanf expects a format string and a pointer to a place in memory where it places what it reads. In your case c points to an undefined place and will overwrite whatever there is in memory.
- why do you place a ";" after the else? The else clause will end with the ";". So your program will do the print every time.
It helps you a lot if you format your code in a more readable way and give the variable names that give hint what they are used for.
Another very important thing is to initialize every variable that you declare. Errors with uninitialized variables are sometimes very hard to find.
I would do it this way:
#include <stdio.h>
int main(int argc, char* argv[])
{
// I read every single character. The getchar function returns an int!
int c = 0;
// This marks the program state whether we must print the next character or not
bool printNext = false;
printf("enter some characters");
// We read characters until the buffer is empty (EOF is an integer -1)
do
{
// Read a single character
c = getchar();
if ( c == '.')
{
// After a point we change our state flag, so we know we have to print the next character
printNext = true;
}
else if( c != EOF )
{
// When the character is neither a point nor the EOF we check the state
if( printNext )
{
// print the character
printf( "%c", c );
// reset the state flag
printNext = false;
}
}
// read until the EOF occurs.
}
while( c != EOF );
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char letter;
char *c;
c = malloc(256);
printf("enter the string : ");
scanf("%s", c);
while( (letter=*(c)) != '\0' )
{
if (letter == '.')
{
c++;
letter=*c;
if(letter!='.')
printf("%c",letter);
else
{
while(letter=='.')
{
c++;
letter=*c;
}
printf("%c",letter);
}
}
c++;
}
printf("\n");
}
My input stream is from a text file with a list of words separated by the \n character.
The function stringcompare is a function that will compare the equivalence of two strings, case insensitive.
I have two string arrays, word[50] and dict[50]. word is a string that would be given by the user.
Basically what I want to do is pass word[] and each word in the text file as arguments of the stringcompare function.
I've compiled and run this code but it is wrong. Very wrong. What am I doing wrong? Can I even use fgetc() like this? would dict[] even be a string array after the inner loop is done?
char c, r;
while((c = fgetc(in)) != EOF){
while((r = fgetc(in)) != '\n'){
dict[n] = r;
n++;
}
dict[n+1] = '\0'; //is this necessary?
stringcompare(word, dict);
}
It is wrong.
The return value of fgetc() should be stored to int, not char, especially when it will be compared with EOF.
You might forgot to initialize n.
You will miss the first character of each line, which is stored to c.
Use dict[n] = '\0'; instead of dict[n+1] = '\0'; because n is already incremented in the loop.
Possible fix:
int c, r;
while((c = fgetc(in)) != EOF){
ungetc(c, in); // push the read character back to the stream for reading by fgetc later
n = 0;
// add check for EOF and buffer overrun for safety
while((r = fgetc(in)) != '\n' && r != EOF && n + 1 < sizeof(dict) / sizeof(dict[0])){
dict[n] = r;
n++;
}
dict[n] = '\0'; //this is necessary
stringcompare(word, dict);
}
I am trying to create a c program that read a file and count specific words.
I tried this code but I don't get any result:
#include<stdio.h>
#include<stdlib.h>
void main
{
File *fp = fopen("file.txt","r+");
int count =0;
char ch[10];
while((fgetc(fp)!=NULL)
{
while((fgetc(fp)!=NULL)
{
if((fgets(ch,3,fp))=="the" || (fgets(ch,3,fp))=="and")
count++;
}
}
printf("%d",count);
}
As you're acquiring data in blocks of 3 at a time, you're assuming that the two words "the" and "and" are aligned on 3 character boundaries. That will not, in general, be the case.
You also need to use strncmp to compare the strings.
As a first review, I'd read line by line and search each line for the words you want.
I'm also unsure as your intention behind having two nested while loops.
You can't compare string pointers with the equality operator, you have to use the strcmp function.
There are also other problems with the code you have. For once, the fgetc calls does not return NULL on errors or problems, but EOF. Otherwise it returns a character read from the file.
Also, your two fgets in the condition will cause reading of two "lines" (though each "line" you read will only be two characters) from the file.
fgets(ch, 3, fp) makes you read 2 characters plus the null-terminator, if you want to read 3 characters and the null-terminator you want fgets(ch, 4, fp) instead. Also, you need to use strcmp to compare strings.
Also, what are all those while loops for ?
if((fgets(ch,3,fp))=="the" || (fgets(ch,3,fp))=="and")
The above line is completely useless.
fgets(ch,3,fp) gets your word from the file to ch[10] . But you cannot compare that using == .
What I would do is use strcmp and give size 4 in fgets (never forget the \o)
You gotta use strcmp() to compare two strings. Not relational operators.
Just out of my head (perhaps not the optimal way, but should be pretty easy to read and understand):
#define WHITE_SPACE(c) ((c)==' ' || (c)=='\r' || (c)=='\n' || (c)=='\t'))
int CountWords(const char* fileName,int numOfWords,const char words[])
{
int count = 0;
FILE* fp = fopen(fileName,"rt");
fseek(fp,0,SEEK_END);
int size = ftell(fp);
fseek(fp,0,SEEK_SET);
char* buf = new char[size];
fread(buf,size,1,fp);
fclose(fp);
for (int i=0,j; i<size; i=j+1)
{
for (j=i; j<size; j++)
{
if (WHITE_SPACE(buf[j]))
break;
}
for (int n=0; n<numOfWords; n++)
{
int len = strlen(words[n]);
if (len == j-i && !memcmp(buf+i,words[n],len))
count++;
}
}
delete[] buf;
return count;
}
Please note, however, that I have not compiled nor tested it (as I said above, "out of my head")...
Take a look at String matching algorithms.
You can also find implementation examples of Boyer-Moore in github
The line
if((fgets(ch,3,fp))=="the" || (fgets(ch,3,fp))=="and")
has a couple of problems:
You can't compare string values with the == operator; you need to use the strcmp library function;
You're not comparing the same input to "the" and "and"; when the first comparison fails, you're reading the next 3 characters from input;
Life will be easier if you abstract out the input and comparison operations; at a high level, it would look something like this:
#define MAX_WORD_LENGTH 10 // or however big it needs to be
...
char word[MAX_WORD_LENGTH + 1];
...
while ( getNextWord( word, sizeof word, fp )) // will loop until getNextWord
{ // returns false (error or EOF)
if ( match( word ) )
count++;
}
The getNextWord function handles all the input; it will read characters from the input stream until it recognizes a "word" or until there's no room left in the input buffer. In this particular case, we'll assume that a "word" is simply any sequence of non-whitespace characters (meaning punctuation will be counted as part of a word). If you want to be able to recognize punctuation as well, this gets a bit harder; for example, a ' may be quoting character ('hello'), in which case it should not be part of the word, or it may be part of a contraction or a posessive (it's, Joe's), in which case it should be part of the word.
#include <ctype.h>
...
int getNextWord( char *target, size_t targetSize, FILE *fp )
{
size_t i = 0;
int c;
/**
* Read the next character from the input stream, skipping
* over any leading whitespace. We'll add each non-whitespace
* character to the target buffer until we see trailing
* whitespace or EOF.
*/
while ( (c = fgetc( fp )) != EOF && i < targetSize - 1 )
{
if ( isspace( c ) )
{
if ( i == 0 )
continue;
else
break;
}
else
{
target[i++] = c;
}
}
target[i] = 0; // add 0 terminator to string
return i > 0; // if i == 0, then we did not successfully read a word
}
The match function simply compares the input word to a list of target words, and returns "true" (1) if it sees a match. In this case, we create a list of target words with a terminating NULL entry; we just walk down the list, comparing each element to our input. If we reach the NULL entry, we didn't find a match.
#include <string.h>
...
int match( const char *word )
{
const char *targets[] = {"and", "the", NULL};
const char *t = targets;
while ( t && strcmp( t, word ))
t++;
return t != NULL; // evaluates to true if we match either "the" or "and"
}
Note that this comparison is case-sensitive; "The" will not compare equal to "the". If you want a case-insensitive comparison, you'll have to make a copy of the input string and convert it all to lowercase, and compare that copy to the target:
#include <stdlib.h>
#Include <ctype.h>
#include <string.h>
...
int match( const char *word )
{
const char *targets[] = {"and", "the", NULL};
const char *t = targets;
char *wcopy = malloc( strlen( word ) + 1 );
if ( wcopy )
{
char *w = word;
char *c = wcopy;
while ( *w )
*c++ = tolower( *w++ );
}
else
{
fprintf( stderr, "malloc failure in match: fatal error, exiting\n" );
exit(0);
}
while ( t && strcmp( t, wcopy))
t++;
free( wcopy );
return t != NULL; // evaluates to true if we match either "the" or "and"
}