#include <stdio.h>
#include <string.h>
int main(){
char c[20], result[50];
int bool = 0, count = 0, i;
while(fgets(c,20,stdin) != NULL){
int stringSize = strlen(c);
if(stringSize == 11){
int ascii = (int)(c[i]);
for(i = 0; i < stringSize; i++){
if(ascii >= 'A' && ascii <= 'Z'){
bool = 1;
}
}
}
}
if(bool == 1){
count++;
strcat(result,c);
}
printf("%d", count);
printf("%s",result);
}
Good morning, I am fairly new to programming, and I've spent quite a while Googling and searching around for this issue already, but I can't seem to wrap my head about it.
Basically I'm trying to filter an fgets so that it reads each string, and if they're capital letters, they're "valid". However, I can't even get the fgets to stop accepting more input.
Edit: The idea is to store in result every String that has 10 capital letters, and for the fgets while loop to break once the user gives no input ('\0')
If you are entering strings from the standard input stream then it is better to rewrite the condition of the while loop the following way
while( fgets(c,20,stdin) != NULL && c[0] != '\n' ){
In this case if the user just pressed the Enter key without entering a string then the loop stops its iterations.
Pay attention to that fgets can append the new line character '\n' to the entered string. You should remove it like
c[ strcspn( c, "\n" ) ] = '\0';
Then you could write
size_t n = strlen( c );
if ( n == 10 )
{
size_t i = 0;
while ( i != n && 'A' <= c[i] && c[i] <= 'Z' ) ++i;
bool = i == 10;
}
Pay attention to that it is a bad idea to use the name bool because such a name is introduced as a macro in the header <stdbool.h>.
Also it seems this if statement
if(bool == 1){
count++;
strcat(result,c);
}
must be within the while loop. And the array result must be initially initialized
char c[20], result[50] = { '\0' };
Related
I'm trying to write a program which gets one or more input lines, and if one line is too long, it gets folded at a maximum number of chars. My approach would be to write the input chars in a first array, of a given length. If Maximum length is reached or '\n' as input, i copy the content in a bigger array which will be the final string to print and get the second line in input. Problem is: it doesn't work and I can't figure out why. Thanks for the help
#include <stdio.h>
#define MAXCOL 10
#define FINAL_LENGTH 300
char line[MAXCOL];
char final_string[FINAL_LENGTH];
extern int fnlstr_pos = 0;
int main()
{
int pos, c;
pos = 0;
while(c=getchar() != EOF)
{
line[pos] = c;
if (pos + 1 >= MAXCOL || c == '\n'){
to_printandi(pos);
pos = 0;
}
++pos;
}
printf("%s", final_string);
}
to_printandi(pos)
int pos;
{
int i;
for(i = 0; i <= pos; ++i){
final_string[fnlstr_pos] = line[i];
++fnlstr_pos;
}
if (final_string[fnlstr_pos] != '\n'){
final_string[++fnlstr_pos] = '\n';
}
++fnlstr_pos;
}
There are several problems in the code. Others have already pointed out the bug in the getchar() line.
More variables and more functions and more code only twist one around in knots. If you take some time to think about what you want to achieve, go slowly, you can get your results with much less effort. Less code full of helpful comments, make for better programs.
EDIT
Looking at code with fresh eyes, I realised that the two lines explicitly setting the 'trailing' byte to '\0' were write 0 overtop of bytes already initialised to 0. Have commented out those two lines as they are superfluous.
#include <stdio.h>
int main () {
char buf[ 1024 ] = { 0 }; // buffer initialised
int ch, cnt = 0, ccnt = 0; // input char and counters
while( ( ch = getchar() ) != EOF ) { // get a character
ccnt++; // count this character
buf[ cnt++ ] = (char)ch; // assign this character
// buf[ cnt ] = '\0'; // string always terminated
if( buf[ cnt-1 ] == '\n' ) // user supplied LF?
ccnt = 0; // reset the counter (for width)
else
if( ccnt == 10 ) { // reached max output width?
buf[ cnt++ ] = '\n'; // inject a LF
// buf[ cnt ] = '\0'; // string always terminated
ccnt = 0; // reset the counter (for width)
}
}
puts( buf ); // output the whole shebang
return 0;
}
0123456789abcdefghijklmnop
qrs
tuv
wxyz
^D // end of input
0123456789
abcdefghij
klmnop
qrs
tuv
wxyz
Like the OP code, this does not test for overrunning the buffer. An easy addition left as an exercise for the reader.
EDIT2:
Then again, why have a buffer to overrun?
#include <stdio.h>
void main( void ) {
for( int ch, n = 0; ( ch = getchar() ) != EOF; /**/ )
if( (n = putchar( ch ) == '\n' ? 0 : n + 1) == 10 )
putchar( '\n' ), n = 0;
}
This question is very broad and it would helpful if you said what the problem is but I can see one issue -- you don't null terminate the final_string variable. add
final_string[fnlstr_pos] = '\0';
before the printf.
Maybe that fixes the problem you are having.
For starters this statement
while(c=getchar() != EOF)
is equivalent to
while( c = ( getchar() != EOF ) )
So c is always equal to1 if EOF is not encountered.
You need to write
while( ( c=getchar() ) != EOF)
And you need to append the input sequence with the terminating zero character '\0' tp form a string.
Another problem is these code snippet with for loop
for(i = 0; i <= pos; ++i){
final_string[fnlstr_pos] = line[i];
++fnlstr_pos;
}
As within the loop the variable fnlstr_pos was increased then this if statement
if (final_string[fnlstr_pos] != '\n'){
final_string[++fnlstr_pos] = '\n';
}
invokes undefined behavior because the variable points to a non-initialized element of the array.
The main problem is here:
while(c=getchar() != EOF)
Given the operator precedence, this will result in the same as:
while(c= (getchar() != EOF))
So c will be 1 (true) inside the loop.
Change this to:
while((c=getchar()) != EOF)
This is the main problem. Just as #Hogan suggested, there are other issues such as not null terminating the strings.
As you declare them global, they will be zeroed so you can get away with that though not in the case the user provides a string with maximum length.
Also it would greatly improve the code if you could use string manipulation functions from <string.h> instead of copying byte by byte.
I need to build a function that gets an input and capitalizes only the first letter, doesn't print numbers, capitalizes after a . for a new sentence, and capitalizes all words between a double quotation marks ".
This is what I got until now:
#include <stdio.h>
#define MAX 100
int main()
{
char str[MAX] = { 0 };
int i;
//input string
printf("Enter a string: ");
scanf("%[^\n]s", str); //read string with spaces
//capitalize first character of words
for (i = 0; str[i] != '\0'; i++)
{
//check first character is lowercase alphabet
if (i == 0)
{
if ((str[i] >= 'a' && str[i] <= 'z'))
str[i] = str[i] - 32; //subtract 32 to make it capital
continue; //continue to the loop
}
if (str[i] == '.')//check dot
{
//if dot is found, check next character
++i;
//check next character is lowercase alphabet
if (str[i] >= 'a' && str[i] <= 'z')
{
str[i] = str[i] - 32; //subtract 32 to make it capital
continue; //continue to the loop
}
}
else
{
//all other uppercase characters should be in lowercase
if (str[i] >= 'A' && str[i] <= 'Z')
str[i] = str[i] + 32; //subtract 32 to make it small/lowercase
}
}
printf("Capitalize string is: %s\n", str);
return 0;
}
I cant find a way to remove all numbers from input and convert all lowercase to uppercase inside a " plus code for not printing numbers if user input them.
if I input
I am young. You are young. All of us are young.
"I think we need some help. Please" HELP. NO, NO NO,
I DO NOT
NEED HELP
WHATSOEVER.
"Today’s date is
15/2/2021"...
I am 18 years old, are you 20 years old? Maybe 30 years?
output:
I am young. You are young. All of us are young.
"I THINK WE NEED SOME HELP. PLEASE" help. No, no no,
i do not
need help
whatsoever.
"TODAY’S DATE IS
//"...
I am years old, are you years old? maybe years?
The C standard library provides a set of functions, in ctype.h, that will help you
Of particular interest, would be:
isdigit() - returns true if digit
isalpha() - returns true if alphabet character
isalnum() - returns true if alpha/numeric character
islower() - returns true if lower case character
isupper() - returns true if upper case character
tolower() - converts character to lower case
toupper() - converts character to upper case
So, for example, you could replace the test/modify with:
if ( islower( str[i] ) )
{
str[i] = toupper( str[i] );
}
Pedantically, islower() and toupper() return an unsigned int but that's a separate matter...
You can remove letters from a string if you keep two indices, one for reading and one for writing. The following loop will remove all digits from a string:
int j = 0; // writing index, j <= i
int i; // reading index
for (i = 0; str[i]; i++) {
int c = (unsigned char) str[i];
if (!isdigit(c)) str[j++] = c;
}
str[j] = '\0';
(I've used to character classification functions from <ctype.h> mentioned in Andrew' answer.)
This is safe, because j will always be smaller or equal to i. Don't forget to mark the end of the filtered string with the nullterminator, '\0'. You can combine this filtering with your already existing code for replacing characters.
In your code, you capitalize letters only if they are directly behind a full stop. That's usually not the case, there's a space between full stop and the next word. It's better to establish a context:
shift: capitalize the next letter (beginning or after full stop.)
lock: capitalize all letters (inside quotation marks.)
When you read a letter, decide whether to capitalize it or not depending of these two states.
Putting the filtering and the "shift context§ together:
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char str[] = "one. two. THREE. 4, 5, 6. \"seven\", eight!";
int shift = 1; // Capitalize next letter
int lock = 0; // Capitalize all letters
int j = 0; // writing index, j <= i
int i; // reading index
for (i = 0; str[i]; i++) {
int c = (unsigned char) str[i];
if (isdigit(c)) continue;
if (isalpha(c)) {
if (shift || lock) {
str[j++] = toupper(c);
shift = 0;
} else {
str[j++] = tolower(c);
}
} else {
if (c == '"') lock = !lock;
if (c == '.') shift = 1;
str[j++] = c;
}
}
str[j] = '\0';
puts(str);
printf("(length: %d)\n", j);
return 0;
}
In order to remove some characters, you should use 2 index variables: one for reading and one for writing back to the same array.
If you are allowed to use <ctype.h>, it is a much more portable and efficient way to test character types.
Also do not use scanf() with protection against buffer overflow. It is as bad as using gets(). Given the difficulty in specifying the maximum number of bytes to store into str, you should use fgets() instead of scanf().
Here is a modified version:
#include <ctype.h>
#include <stdio.h>
#define MAX 100
int main() {
char str[MAX];
int i, j;
unsigned char last, inquote;
//input string
printf("Enter a string: ");
if (!fgets(str, sizeof str, stdin)) { //read string with spaces
// empty file
return 1;
}
last = '.'; // force conversion of first character
inquote = 0;
//capitalize first character of words
for (i = j = 0; str[i] != '\0'; i++) {
unsigned char c = str[i];
//discard digits
if (isdigit(c)) {
continue;
}
//handle double quotes:
if (c == '"') {
inquote ^= 1;
}
//upper case letters after . and inside double quotes
if (last == '.' || inquote) {
str[j++] = toupper(c);
} else {
str[j++] = tolower(c);
}
if (!isspace(c) && c != '"') {
// ignore spaces and quotes for the dot rule
last = c;
}
}
str[j] = '\0'; // set the null terminator in case characters were removed
printf("Capitalized string is: %s", str);
return 0;
}
I am trying to find the no of lower and uppercase characters from a input.
here's my code:
#include <stdio.h>
#include <string.h>
int main()
{
char cAFirst[25];
int k = 0,uc =0 ,lc =0 ;
fgets(cAFirst,25,stdin);
// printf("out: %d \n",k);
for (size_t i = 0; i < 25; i++) {
k = (int)cAFirst[i];
if ((k <= 90) && (k >= 65)) {
uc++;
}
if ((k >= 97) && (k <= 122)) {
lc++;
}
}
printf("Uppercase Letters=%i \nLowercase Letters=%i \n",uc,lc );
return 0;
}
lowercase (lc) is ok, but value of uc is randomly incremented.
I have already tried changing formatting of printf and it sometimes work, but problem is i have to submit this code with same formatting given above.
Rather then always iterate 25 times, iterate until the end of input is detected.
// for (size_t i = 0; i < 25; i++) {
for (size_t i = 0; cAFirst[i]; i++) { // detect null character.
Considering this snippet from OP's posted code:
char cAFirst[25]; // <- Uninitialized, the contents are indeterminated
// ...
fgets(cAFirst,25,stdin); // <- We don't know if it succeeded or not
// ...
for (size_t i = 0; i < 25; i++) {
// ... ^^^^^^
}
It copies up to 24 chars from stdin to the array (including the newline, if present), also adding the null-terminator (if no stream error occurred), but when the loop is executed, it goes over all the 25 char of the array, even if the inputted string is shorter, taking into account chars with indeterminate value.
To avoid this, we just have to test only the characters which were actually read from the input stream, by counting them or using the null-terminator as a sentinel.
We could intialize the array (to zero) and also avoid the use of repeated magic numbers, which is error prone.
#include <stdio.h>
// I'd use a bigger value, like 256, but OP's use case is not specified.
enum {
BUF_SIZE = 25
};
int main(void)
{
// All the elements of the array are set to zero, not only the first.
char buf[BUF_SIZE] = {'\0'};
// ...
Now, even if all the chars in the array are tested in the previous loop, there won't be spurious values and the statistics will be consistent. This is not a real solution, though, and while it is commonly suggested to initialize all the variables before their use, in this case it is not necessary.
As noted by chux, the return value of functions like fgets should be checked, to verify that the operation has succeeded and that our variables are in a valid state.
if ( fgets(buf, BUF_SIZE, stdin) == NULL ) {
if (feof(stdin)) {
fprintf(stderr, "Abnormal end of input.\n");
// The contents of the array are not altered
}
if (ferror(stdin)) {
fprintf(stderr, "A stream error occurred.\n");
// The contents of the array are indeterminated, maybe not even null-terminated
}
exit(EXIT_FAILURE);
}
The key point is to be sure that, after this call, the array is null-terminated. Even a check like the following could be enough:
if ( fgets(buf, BUF_SIZE, stdin) == NULL ) {
fprintf(stderr, "An error occurred while reading from stdin.\n");
buf[0] = '\0';
// Continues the program despite the error, but with a valid (empty) string
}
It's worth remembering that any further characters besides the ones read, remain in the input stream.
Now that we have a valid (null-terminated) array, we can loop through it:
int uc = 0, lc = 0;
for (size_t i = 0; buf[i] != '\0'; i++) {
// which can also be written as 'for (size_t i = 0; buf[i]; i++) {'
// It's also more readable without magic numbers:
if ( 'A' <= buf[i] && buf[i] <= 'Z' ) {
uc++;
}
else if ( 'a' <= buf[i] && buf[i] <= 'z' ) {
lc++;
}
}
printf("Uppercase Letters = %i\nLowercase Letters = %i\n", uc, lc);
return EXIT_SUCCESS;
}
The previous snippet may be generalized from ASCII codes using functions like isupper and islower defined in header <ctype.h>. Also, the actual length of the string can be used to limit the for-loop:
// Length of the maximum initial segment of the array, that consists of
// only the characters not equal to a newline or null character
size_t length = strcspn(buf, "\n");
int uc = 0, lc = 0;
for (size_t i = 0; i < length; i++) {
unsigned char k = buf[i];
if ( isupper(k) ) {
uc++;
}
else if ( islower(k) ) {
lc++;
}
}
// ...
You should first use a way to iterate your string only once maybe a while loop and try to read not just what you need but also what there could be which should not be counted. What happens if there is \t or \n Do you need them to count too?
Here is an approach which can help you to understand that:
#include <stdio.h>
int main( void )
{
char string[] = "AbcDEfgHiJKlmnOPqrstUVWxyZ\n§$%$§";
int uc, lc, i, others;
uc = lc = i = others = 0;
while ( string[i] )
{
if ( string[i] >= 'A' && string[i] <= 'Z' )
{
uc++;
}else if ( string[i] >= 'a' && string[i] <= 'z' ){
lc++;
}else{
others++;
}
i++;
}
if ( i == ( lc + uc + others ) )
{
printf( "OK\n\n" );
printf("Uppercase Letters = %i \nLowercase Letters = %i \nOthers = %d \n", uc, lc, others );
printf("Total = %d\n", i );
}else
{
printf("Something went Wrong.\n\n");
}
}
Your if/else statements could be easy replaced by the functions isupper( string[i] ) and islower( string[i] ) which are found in ctype.h
if ( isupper( string[i] ) )
{
uc++;
}else if ( islower( string[i] ) )
{
lc++;
}else{
others++;
}
Even if while is true getchar iterates one time. I tried my code with getchar in while condition and body, but it doesn't work.
int main() {
char* s = malloc(sizeof(char)) /*= get_string("Write number: ")*/;
char a[MAXN];
int i = 0;
do {
a[i] = getchar();
*s++ = a[i];
i++;
} while (isdigit(a[i-1]) && a[i-1] != EOF && a[i-1] != '\n' && i< MAXN);
/*while (isdigit(*s++=getchar()))
i++;*/
*s = '\0';
s -= i;
long n = conversion(s);
printf("\n%lu\n", n);
}
As others have pointed out, there isn't much use for s because a can be passed to conversion. And, again, the malloc for s only allocates a single byte.
You're incrementing i before doing the loop tests, so you have to use i-1 there. Also, the loop ends with i being one too large.
Even for your original code, doing int chr = getchar(); a[i] = chr; and replacing a[i-1] with chr can simplify things a bit.
Better yet, by restructuring to use a for instead of a do/while loop, we can add some more commenting for each escape condition rather than a larger single condition expression.
#define MAXN 1000
int
main(void)
{
char a[MAXN + 1];
int i;
for (i = 0; i < MAXN; ++i) {
// get the next character
int chr = getchar();
// stop on EOF
if (chr == EOF)
break;
// stop on newline
if (chr == '\n')
break;
// stop on non-digit
if (! isdigit(chr))
break;
// add digit to the output array
a[i] = chr;
}
// add EOS terminator to string
a[i] = 0;
unsigned long n = conversion(a);
printf("\n%lu\n",n);
return 0;
}
Code does not allocate enough memory with malloc(sizeof(char)) as that is only 1 byte.
When code tries to save a 2nd char into s, bad things can happen: undefined behavior (UB).
In any case, the allocation is not needed.
Instead form a reasonable fixed sized buffer and store characters/digits there.
// The max digits in a `long` is about log10(LONG_MAX) + a few
// The number of [bits in an `long`]/3 is about log10(INT_MAX)
#define LONG_DEC_SZ (CHAR_BIT*sizeof(long)/3 + 3)
int main(void) {
char a[LONG_DEC_SZ * 2]; // lets go for 2x to allow some leading zeros
int i = 0;
int ch; // `getchar()` typically returns 257 different values, use `int`
// As long as there is room and code is reading digits ...
while (i < sizeof a && isdigit((ch = getchar())) ) {
a[i++] = ch;
}
a[i++] = '\0';
long n = conversion(a);
printf("\n%ld\n", n);
}
To Do: This code does not allow a leading sign character like '-' or '+'
I am trying to write a program that checks to see if a word inputed to a program matches one of the predefined keywords. Input is going to be coming from a text file and the text file will have a single word in it. So far the text file I have just has the word 'crackerjack' which means the program should clearly print 'Match Found' but it is not currently doing that. Here is my code, does anything stand out to you guys? Thanks
#define NUM 4
#define SIZE 11
int isAlpha(char);
//Returns 1 if it is an Alphabetical character, 0 if it is not
int isAlpha(char c) {
return (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z');
}
int main() {
char message[141];
int charCount = 0, c = 0, matchCheck = 0;
char keywords[NUM][SIZE] = {
"crackerjack",
"Hey",
"dog",
"fish"
};
//Removes non alphabetical characters
while((c = getchar()) != EOF && charCount <= 140) {
if(isAlpha(c)){
message[charCount] = c;
charCount++;
}
printf("%d", isAlpha(c));
}
//checks if message matches keyword
for (int i = 0; i < NUM; i++) {
for (int j = 0; j < SIZE; j++) {
//Check if current two characters match
if (message[j] == keywords[i][j]) {
//Check if the two matched characters are the null terminator character
if (message[j] == '\0' && keywords[i][j] == '\0')
matchCheck = 1;
break;
}
//if characters are not the same, break from loop
else {
break;
}
}
}
//prints "Match Found!" if there was a match
if (matchCheck == 1) {
printf("Match Found!\n");
}
}
There are 3 problems in your code. Two of them have already been addressed:
Ensure that SIZE is big enough to include a '\0' at the end of the longest keyword
Ensure that the text file includes a '\0' at the end of the word. If it is not the case or it is out of your control, you can always manually end the string with a '\0' after reading it.
You are missing brackets on your second if statement. This causes the break statement to be executed every time the first if statement is entered.
SIZE is too small. Make room for '\0'.
#define SIZE 12
char keywords[NUM][SIZE] = {
"crackerjack",
...
};
I see now this is effectively what #user3121023 said. Credit to #user3121023.