I am a new to programming. I am trying to write a program that reads lines, words and characters from a text file. Here is the code below.
#include "stdio.h"
#include "stdlib.h"
#define IN 1
#define OUT 0
int main (int argc, char *argv[]) {
FILE *input;
int character, newword, newline, state;
char c;
state = OUT;
character = newline = newword =0;
input = fopen(argv[1], "r");
if ( input == NULL){
printf("Error! Can not read the input\n");
exit(-1);
}
while ((c = fgetc(input)) != EOF){
character++;
if (c <'a' && c >'z'){;}
if ( c <'A' && c >'Z'){;}
if (c == '\n'){
newline++;
}
if (c == ' ' || c == '\n' || c == '\t'){
state = OUT;
}
else if (state == OUT){
state = IN;
newword++;
}
}
printf("The number of lines: %d\n", newline);
printf("The number of words: %d\n", newword);
printf("The number of characters: %d\n", character);
fclose(input);
}
I have been trying to figure how not to read special characters such as !, #, #, $, %, ^, &, *, (, ), _, +.
I tried using if statements so it won't read the special characters but it reads it. I think one the if statement for the capital letters is wrong because it probably will not read lower case letters.
In the file the following text is in it,
!!.
and it outputs in terminal:
The number of lines: 2
The number of words: 5
The number of characters: 7
However, if I take out the two for loops (c < 'A' && c > 'Z') and (c < 'a' && c > 'z'), then the output becomes
The number of lines: 2
The number of words: 1
The number of characters: 7
Any hints to fix this problem (I do not want the Answer!)?
Your if must be something like:
if ('a' <= c && c <='z'){character++;}
else if ( 'A' <= c && c <='Z'){character++;}
The easiest way to solve your problem is to increase your character counter when the character is between the interval 'a' and 'z' or the interval 'A' and 'Z', and then, since the escape sequence '\n' creates a new line, this also means that you are dealing with a new word, thus you should increment this counter too. And finally you can check for the space or the horizontal tab to increment the new word counter.
if ((c <'a' && c >'z') || ( c <'A' && c >'Z')){
++character;
}
else if (c == '\n'){
++newline;
++newword;
}
else if (c == ' ' || c == '\t'){
++newword;
}
Related
Brand new C coder here. In my first C course in school. I have experience in java but this course is all in C. I have homework to create a program that reads the contents of a file and counts the number of upper and lower case letters, vowels, consonants and digits. The program is not supposed to have any arguments, but will take a .txt file from the command line via redirection. My question is, how do I correct my current code to read from stdin each character of the file, whether it be a letter or a number? I'm really struggling with how read the contents of the file from stdin, read each character and then decide which category it belongs in. Any help would be appreciated. Thanks.
I'll be running the program like this...
$ program < testFile.txt
Where testFile.txt will contain the following text:
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
int upper = 0; // Number of upper case letters
int lower = 0; // Number of lower case letters
int vowel = 0; // Number of vowels
int consonant = 0; // Number of constants
int digits = 0; // Number of digits
int total = 0; // Total number of characters in file
int i =0;
char value[100];
fgets(value, 100, stdin);
while(value[i] != '\0');
{
if (value[i] >= 'A' && value[i] <= 'Z')
{
upper++;
if (value[i] == 'A' || value[i] == 'E' || value[i] == 'I' || value[i] == 'O' || value[i] == 'U' || value[i] == 'Y')
{
vowel++;
}
else {
consonant++;
}
}
else if (value[i] >= 'a' && value[i] <= 'z')
{
lower++;
if (value[i] == 'a' || value[i] == 'e' || value[i] == 'i' || value[i] == 'o' || value[i] == 'u' || value[i] == 'y')
{
vowel++;
}
else {
consonant++;
}
}
else if (value[i] >= '0' && value[i] <= '9')
{
digits++;
}
total++;
i++;
}
printf("upper-case: %d", upper);
printf("\nlower-case: %d", lower);
printf("\nvowels: %d", vowel);
printf("\nconsonants: %d", consonant);
printf("\ndigits: %d", digits);
printf("\ntotal: %d", total);
printf("\n");
return 0;
I expect output to show how many upper case letters, lower case letters etc.
But once I run $ program < testFile.txt, it just sits there, no output to command line or anything.
Remove the semicolon after the while statement. :-)
while(value[i] != '\0');
This is your most obvious problem, it basically means:
while value[i] != '\0':
do nothing
end while
In other words, if it enters the loop, it will never exit it, because nothing changes that would affect the condition under which the loop continues.
There are other problems as well such as the fact that you will only process the first line rather than the whole file. The whole idea of using fgets and processing a line is unnecessary when you can just start with the following filter skeleton:
int ch;
while ((ch = getchar()) != EOF) {
/* process ch */
}
This will process an entire file character by character until all characters are done (or until an error occurs) so you can just tailor the body loop to do what you need - you've basically done that bit in your code with the loop over the line characters.
I would suggest not using the following code (since this is classwork) but you can also make better use of flow control constructs and library functions (from ctype.h and string.h), something like:
while ((ch = getchar()) != EOF) {
// Lib functions to detect upper/lower-case letters.
if (isupper(ch)) {
++upper;
} else if (islower(ch))
++lower;
}
// And to detect letter/digit type.
if (strchr("aeiouAEIOU", ch) != NULL) {
++vowel;
} else if (isalpha(ch)) {
++consonant;
} else if (isdigit(ch)) {
++digits;
}
++total;
}
This is particularly important since there's no actual guarantee that non-digit characters will be consecutive.
Once again i find myself relatively lost and seeking knowledge from my peers.
What I am needing to do is to write a program that takes in an encoded language that adds the leters 'u' 't' after ever consonant and output into english. So the input Hutelutluto would be outputted as hello. At first I thought i had it figured out, but then my professor said i had to store the initial input in a character array and display it. Then use that character array to output the modified translation.
I have tried several different angles, one trying to modify my readstring function to fit my modification parameters. It always ends up becoming a mess and giving me unexpected outputs.
Essentially I believe that I need help feeding the character array into the while loop, but when I try I get an error stating that i have a pointer comparison to integer error.
Here is my edition of my code where i believe I was the closest to solving the problem. At the moment the while works independently from the readstring function. I am sure I am overthinking the problem, but i just not sure how to work out the kinks.
:
/*
Tut language
By: Steven
*/
# include <stdio.h>
void readstring(char *, int);
int main (void){
char input [50];
char output;
char trash;
//initiation
printf("\n\t*Hi! Welcome to the assemble of Tut*\n");
printf("I can help you decode/encode a message to and from the code called Tut!\n");
printf("Enter a sentence to be translated frome Tut - English: ");
readstring(input, 50);
printf("Your Tut sencence is: %s \n",input);
while (output != '\n') {
output = getchar();
if(output == '\n'){//escape sequence
break;
}
if((output != 'a') && (output != 'e') && (output != 'i') && (output != 'o') && (output != 'u') && (output != 'y') && (output != ' ')){
putchar(output);
trash = getchar();
trash = getchar();
}else{
putchar(output);
}
}
return 0;
}// end main
//function lists start
void readstring(char * buffer, int size) {
int x;
char c = getchar( );
if( c == '\n' ) {
c = getchar( );
}
for(x = 0 ; (x < (size-1)) && c != '\n' ; x++) {
buffer[x] = c;
c = getchar( );
}
buffer[x] = '\0';
}
Any help or feedback will be greatly appreciated!
Thank your for your time!
p.s.
After taking your advice into consideration i edited my code, but it seems as if it is ignoring all input after the first. I even tried changing the !='\n' condition to just i < 50, but i got the same results.
Line of code after taking Tim's advice:
for (i = 0; input [i] != '\n'; ++i){
output = input[i];
if((output != 'a') && (output != 'e') && (output != 'i') && (output != 'o') && (output != 'u') && (output != 'y') && (output != ' ')){
putchar(output);
trash = getchar();
trash = getchar();
}else{
putchar(output);
}
}
The main problem is in your while loop. In this loop, you are using getchar, which tries to read from stdin. However, you have already read your input, and it is stored in buffer.
So, you should get your characters from buffer instead of reading them again.
Your readstring function already calls getchar to read characters from the user's terminal, so you should not need to call it again after readstring is done. Instead, use a for loop to set output to each character of the input string in turn:
int i;
for i = 0; input[i] != '\n'; ++i {
output = input[i]
if((output != 'a') && (output != 'e') && (output != 'i') && (output != 'o') && (output != 'u') && (output != 'y') && (output != ' ')){
...
… in a character array, i have no idea how I am going to skip
those next two character?
You skip characters by incrementing the array index. Change
trash = getchar();
trash = getchar();
to
input[++i] && input[++i] || --i; // step back if at end of string
Also, since the input string is terminated by \0 rather than \n, change
for (i = 0; input [i] != '\n'; ++i){
to
for (i = 0; input[i]; ++i)
{
I'm new to programming and learning C through a book.
The author of the book explains about logical operators (AND, NOT and OR) by giving the following example which counts the number of characters except the double or single quotes and period character.
I couldn't understand how it counts the number of characters except the quotes and period character. I understand that with the AND operator both conditions should be true.
#include <stdio.h>
#define PERIOD '.'
int main(void)
{
char ch;
int charcount = 0;
while ((ch = getchar()) != PERIOD)
{
if (ch != '"' && ch != '\'')
charcount++;
}
printf("There are %d non-quote characters.\n", charcount);
return 0;
}
I will try to explain you the main part of the code :
while ((ch = getchar()) != PERIOD)
{
Here, it will check every character contained in your text, as long as the character differ from PERIOD, which is a dot, so it simply check all of the characters in the sentence.
if (ch != '"' && ch != '\'')
charcount++;
}
Here, it adds 1 to the charcount if the condition is true. For the if to return true, both ch != '"' and ch != '\'' must be true ! The && operator is a logical AND, and for an AND to return true (1), both conditions must be equal to 1. So if the character is equal to " or ', the AND will return 0, and so we won't add 1 to the charcount.
This condition if (ch != '"' && ch != '\''), is checking if the entered character is "or ' if not then it increments the count of characters otherwise not. If user enterd d or #, it will satisfy the condition because ASCII value of # is not equal to " or ', and the count will get incremented.
Well, for each char returned by getchar() and stored in ch (from an input stream, like a keyboard or a file) it will test if it's not a double quote (ch != '"') and if it's not a quote (ch != '\'')
\ is an escape character, which means '\'' is the char '
If it's neither of them, then it will increments the counter (charcount++;).
And this will go on as long as getchar() doesn't return a period ((ch = getchar()) != PERIOD)(if it does, the PERIOD won't be counted as the code will step out the will loop immediately).
You can skip using continue:
#include<stdio.h>
#define PERIOD '.'
int main(void)
{
char ch;
int charcount = 0;
while ((ch = getchar()) != PERIOD)
{
if (ch != '"' && ch != '\''){
continue;
}
charcount++;
}
printf("There are %d non-quote characters.\n", charcount);
return 0;
}
Output:
./program
Michi"""LoL'''Another'"LoL.
There are 8 non-quote characters.
I'm learning c language and I hit a wall, if you would like to help me I appreciate (here is the ex: "Write a program that reads characters from the standard input to end-of-file. For each character, have the program report whether it is a letter. If it is a letter, also report its numerical location in the alphabet and -1 otherwise." btw is not homework).The problem is with the \n i don't know how to make it an exception. I'm new around here please let me know if I omitted something. Thank you for your help.
int main(void)
{
char ch;
int order;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
printf("%c", ch);
if (ch >= 'A' && ch <= 'Z')
{
order = ch - 'A' + 1;
printf(" %d \n", order);
}
if (ch >= 'a' && ch <= 'z')
{
order = ch - 'a' + 1;
printf(" %d \n", order);
}
if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
{
if (ch == '\n');
else if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
printf(" -1 \n");
}
}
system("pause");
}
You are talking about an "exception" which can be interpreted in other ways in programming.
I understand that you want that '\n' be "excepted" in the set of nonalphabetical characters, that is, that it doesn't generate the error value -1.
Since you are using console to run the program, a sequence of character is going to be read till ENTER key is pressed, which generates the character \n. So, I'm not pretty sure that the while() condition you used, that compares against EOF, it's a good decision of yours.
I would put there directly the comparisson against '\n'.
while ((ch = getchar()) != '\n')
To inform if ch is a letter or not, we could use string literals. The following use of string assignment would deserve more explanation, but I will omit it. It's valid with string literals:
char *info;
if (order != -1)
info = "is a letter";
else
info = "is not a letter";
You are assuming an encoding where the letters are in contiguous increasing order (as in ASCII).
By assuming that, it's enough to work with uppercase or lowercase letters, since you are only interested in the position that the letter occupy in the alphabet. So, you can choose to work with uppercase, for example, in this way:
if (ch >= 'a' && ch <= 'z')
ch = (ch - 'a' + 'A');
The effect of that line of code is that ch is converted to uppercase, only if ch is a lowercase letter. Another kind of character is not affected.
As a consequence, from now on, you only have uppercase letters, or nonalphabetical characters.
Then it's easy to code the remaining part:
if (ch >= 'A' && ch <= 'Z')
order = ch - 'A' + 1; // It brings no. position of letter in alphabet
else
order = -1; // This is the erroneous case
A printf() at the end of the loop could bring all the information about the character:
printf(" %16s: %4d \n", info, order);
The resulting code is shorter in more clear:
#include <stdio.h>
int main(void) {
char ch;
int order;
char *info;
while ((ch = getchar()) != '\n') {
printf("%c",ch);
if (ch >= 'a' && ch <= 'z') /* Converting all to uppercase */
ch = (ch - 'a' + 'A');
if (ch >= 'A' && ch <= 'Z')
order = ch - 'A' + 1; /* Position of letter in alphabet */
else
order = -1; /* Not in alphabet */
if (order != -1)
info = "is a letter";
else
info = "is not a letter";
printf(" %16s: %4d \n", info, order);
}
}
If you need to end the input by comparing against EOF, then the type of ch has to be changed to int instead of char, so you can be sure that the EOF value (that is an int) is properly held in ch.
Finally, this means that ch needs initialization now, for example to a neutral value in the program, as '\n'.
Finally, just for fun, I add my super-short version:
#include <stdio.h>
int main(void) {
int ch, order;
while ((ch = getchar()) != '\n') {
order = (ch>='a' && ch<='z')? ch-'a'+1:((ch>='A' && ch<='Z')? ch-'A'+1: -1);
printf("%c %8s a letter: %4d \n", ch, (order != -1)? "is":"is not", order);
}
}
The C language does not have exceptions. Exceptions were first introduced into programming in C++. You can do it manually in C using setjmp() and longjmp(), but it really isn't worth it.
The two most popular of doing error handling in C are:
Invalid return value. If you can return -1 or some other invalid value from a function to indicate 'there was an error', do it. This of course doesn't work for all situations. If all possible return values are valid, such as in a function which multiplies two numbers, you cannot use this method. This is what you want to do here - simply return -1.
Set some global error flag, and remember to check it later. Avoid this when possible. This method ends up resulting in code that looks similar to exception code, but has some serious problems. With exceptions, you must explicitly ignore them if you don't want to handle the error (by swallowing the exception). Otherwise, your program will crash and you can figure out what is wrong. With a global error flag, however, you must remember to check for them; and if you don't, your program will do the wrong thing and you will have no idea why.
First of all, you need to define what you mean by "exception"; do you want your program to actually throw an exception when it sees a newline, or do you simply want to handle a newline as a special case? C does not provide structured exception handling (you can kind-of sort-of fake it with with setjmp/longjmp and signal/raise, but it's messy and a pain in the ass).
Secondly, you will want to read up on the following library functions:
isalpha
tolower
as they will make this a lot simpler; your code basically becomes:
if ( isalpha( ch ) )
{
// this is an alphabetic character
int lc = tolower( ch ); // convert to lower case (no-op if ch is already lower case)
order = lc - 'a' + 1;
}
else
{
// this is a non-alphabetic character
order = -1;
}
As for handling the newline, do you want to just not count it at all, or treat it like any other non-alphabetic character? If the former, just skip past it:
// non-alphabetic character
if ( ch == '\n' )
continue; // immediately goes back to beginning of loop
order = -1;
If the latter, then you don't really have to do anything special.
If you really want to raise an honest-to-God exception when you see a newline, you can do something like the following (I honestly do not recommend it, though):
#include <setjmp.h>
...
jmp_buf try;
if ( setjmp( try ) == 0 ) // "try" block
{
while ( (ch = getchar() ) != EOF )
{
...
if ( ch == '\n' )
longjmp( try, 1 ); // "throw"
}
}
else
{
// "catch" block
}
I'm having hard time trying to understand why you even try to handle '\n' specifically.
You might be trying to implement something like this:
int main(void)
{
char ch;
int order;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
printf("%c", ch);
if (ch >= 'A' && ch <= 'Z') {
order = ch - 'A' + 1;
printf(" %d \n", order);
} else if (ch >= 'a' && ch <= 'z') {
order = ch - 'a' + 1;
printf(" %d \n", order);
} else if (ch == '\n') { } else {
printf(" -1 \n");
}
}
system("pause");
}
While this is a good solution, I would recommend rewriting it in a more optimal way:
int main(void)
{
char ch;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
int order;
if (ch != '\n'){
if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {
order = ch & 11111B;
printf("Letter %d\n", order);
} else {
order = -1;
printf("Not letter: %d\n", order);
}
}
}
system("pause");
}
This way the program relies on specific way letters coded in ASCII
So for an intro to C class we have to write a program that will count the number of lines, characters, and words in a file. In the program a word is defined as a sequence of letters, digits, and apostrophes that begins with a letter. For some reason the logic for counting words just isn't working for me, maybe it's because I'm new to C or because I've always been bad at formulating logic. My code now, when passed in
hey whats up\n
hey what's up\n
hey wh?ts 'p\n
returns 3 lines, 31 words, 40 characters. Thanks for any help, I know this is a super lame question it's just driving me insane.
Here is my code:
#include <stdio.h>
typedef enum yesno yesno;
enum yesno {
YES,
NO
};
int main() {
int c; // character
int nl, nw, nc; // number of lines, words, characters
yesno inword; // records if we are in a word or not
yesno badchar;
// initialize variables:
badchar=NO;
inword = NO;
nl = 0;
nw = 0;
nc = 0;`
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
inword = NO;
else if (inword == NO) {
inword = YES;
}
while (inword == YES){
if (( c<'A' || c>'Z')||(c<'a'||c>'z')||(c<'0'|| c>'9') ){
inword= NO;
//badchar = YES;
}
if (( c<'A' || c>'Z')||(c<'a'||c>'z')|| (c<'0'|| c>'9') ||(c!= '\'')){
nw=nw;
inword = NO;
//badchar=YES;
}
if(badchar==NO){
nw++;
badchar=NO;
inword= NO;
}
}
}
printf("%d %d %d\n", nl, nw, nc);
}
One problem is this condition:
if (( c<'A' || c>'Z')||(c<'a'||c>'z')||(c<'0'|| c>'9') ){
inword = NO;
Consider a value of c such as:
'A': this is going to be less than 'a', so you'll switch to inword = NO.
'a': this is going to be greater than 'Z', so you'll switch to inword = NO.
'0': this is going to be less than 'A', so you'll switch to inword = NO.
You need to use && between the sets of conditions:
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && (c < '0' || c > '9')){
Or, better, you could use the macros/functions from <ctype.h>:
if (!isupper(c) && !islower(c) && !isdigit(c))
but that can be abbreviated to:
if (!isalnum(c))
You'll need to review the other tests too. There could be other problems too, but I've simply not reviewed the rest of the code.
I've never programmed C. But when I've programmed this same thing in other languages, it's not too tough. For word count, replace "\n" with space, then split the string into an array using a space as the delimiter, and finally count the number of elements in the array. Similar thing to get the line count: split the string into an array using "\n" as the delimiters, then count the number of elements in the array.