pangram function is not working in c - c

#include<stdio.h>
#include<ctype.h>
#include<stdbool.h>
#include<string.h>
#define number_of_letters 26
bool IsPangram(char* string);
int main(){
char check[100];
when i put the output as "the quick brown fox jumps over the lazy dog" the output is no a pangram
and when i put a to z values on one single line is gives the correct output
scanf("%s",&check);
if(IsPangram(check)){
printf("the string entered is pangram");
}
else{
printf("not a pangram");
}
return 0;
}
there is the function for pangram
bool IsPangram(char* string){
bool flags[number_of_letters];
int size=strlen(string);
bool ispangram=true;
int i;
char c;
// for all the alfabets to be setting them to false
for(i=0;i<number_of_letters;i++){
flags[i]=false;
}
// for converting the uppper case letter to the small one
for(i=0;i<size;i++){
c=tolower(string[i]);
if(islower(c)){
flags[string[i]-'a']=true;
}
}
// for checking the the lettters to no pangram
for(i=0;(i<number_of_letters && ispangram==true);i++){
if(flags[i]==false){
ispangram=false;
}
}
return ispangram;
}

You don't need use & when passing a string as a char *, since arrays decay to pointers when passed as parameters.
So:
scanf("%s",&check);
should be:
scanf("%s", check);
And some general advice: turn on compiler warnings to help catch simple mistakes such as this, and learn basic debugging techniques (stepping through code in your debugger, adding strategic printf statements, etc).

scanf() with the %s format specifier will stop at whitespace. Try fgets(check,100,stdin) instead... that will read (up to) a full line, and limit the number of characters to 99 + nul so you won't exceed the size of check. It may leave a newline as the last character, but your algorithm would ignore that anyway.
Additionally, in IsPangram(), c should be an int instead of a char (to match tolower() etc.), and change this:
// for converting the uppper case letter to the small one
for(i=0;i<size;i++){
c=tolower(string[i]);
if(islower(c)){
flags[string[i]-'a']=true;
}
}
...to this:
// for converting the uppper case letter to the small one
for(i=0;i<size;i++){
c=tolower(string[i]); /* <== c will always be lowercase */
if(isalpha(c)){ /* <== Check that c is a letter */
flags[c-'a']=true; /* <== use c, as string[i] may be uppercase */
}
}
...for the reasons indicated in the added comments.

scanf cannot get strings with spaces. So use fgets
fgets(check,sizeof(check),stdin);
Or use
scanf("%[^\n]s",check);
This reads a string till a newline character is encountered.
The default scanf stops reading when a space is encountered.

Here you go:
#include <ctype.h>
void uc(char*s){for(;*s;*s=toupper(*s),s++);}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char*argv[])
{int i,j,n=0,c[256]={0};
char*s,*w[1024]={NULL};
do w[n]=malloc(1024),fgets(w[n],1024,stdin),w[n][strlen(w[n])-1]='\0',uc(w[n]),n++;
while(n<1024&&strlen(w[n-1]));
for(--n,i=0;i<n;++i)
for(j=0;j<strlen(w[i]);++j)
c[w[i][j]]=1;
for(j=0,i='A';i<='Z';++i)j+=c[i];
printf("It's %sa pangram\n",j==26?"":"not ");
for(i=0;i<=n;free(w[i++]));}

Related

How to separate character and number from string in c program

For example, I want to separate the string "0013subdivision" into 0013 (as an integer that can do addition, subtraction, etc. not char) and subdivision (as a char itself) in the given string.
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
char location[10]; /* for the input with number and letter */
char x;
int house[10]; /* for the integer that will be separated from the string */
int main()
{
printf("Input: ");
scanf ("%s", &location[x]);
x=0
for (x=0; location[x]!='\0'; x++ );
return 0;
}
Based on my research, the code atoi is used to convert the converted value back to int (if I'm not mistaken) but I don't know when to place the function.
location is char array, if you are reading as string use only %s with string name only, index not required.
scanf ("%s", &location[x]); --> scanf ("%s", location);
After separating only int from char array you need to store one int value into house.
int house[10] --> int house.
Here is the code for extracting only int from string :
char location[10]; /* for the input with number and letter */
int x;
int house = 0 ; /* for the integer that will be separated from the string */
int main()
{
printf("Input: ");
//scanf ("%s", &location[x]);
scanf ("%s", location);
for (x=0; location[x]!='\0'; x++ ) {
if(location[x]>='0' && location[x]<='9') {
house =(house * 10) + (location[x]-48);
}
}
printf("int part = %d \n",house);
return 0;
}
The main problem in the code is
scanf ("%s", &location[x]);
Where you did not impose any limit on the scanning. An input like 0013subdivision will cause out of bound memory access leading to undefined behavior.
Always limit the input size with the length modifier, like, for an array defined as
char location[10]
use the conversion specification like
scanf ("%9s", location); // (i) one element saved for terminating null
// (ii) the array name decays to the pointer to 1st element
//in case of an argument to a function call.
Then, you don't need an integer array to store the extracted integer. A singular variable would suffice.
However, i'd like to suggest a much robust way:
read the user input using fgets()
then, scan the input using sscanf() and appropriate conversion specifier, like %4d%9s or alike.
The most correct way to do this is to use the strto... family of functions from stdlib.h. For example:
printf("%ld\n", strtol(str, NULL, 10));
The atoi family of functions should never be used for any purpose, since they have broken error handling and can be 100% replaced by the strto... functions.
You could use the scanf family of functions but they are needlessly slow and notoriously dangerous, so I don't really see the point of using them here.
If you are interested in implementing the actual copying manually, for learning purposes, it is fairly trivial:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
const char str[] = "0013subdivision";
char number_part [sizeof(str)];
char letter_part [sizeof(str)];
size_t i;
for(i=0; str[i]!='\0' && isdigit(str[i]); i++) // find where the letters start
{}
memcpy(number_part, &str[0], i); // copy digit part
number_part[i] = '\0'; // append null terminator
memcpy(letter_part, &str[i], sizeof(str)-i); // copy letter part + null term
puts(number_part);
puts(letter_part);
printf("%ld\n", strtol(str, NULL, 10));
}
If the string is a run-time variable, you have to use strlen(str)+1 instead of sizeof().
strtol converts string to number and also gives you back the character it stopped on, i.e. first character after number.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char* const input = "0013subdivision";
const char* string;
const long number = strtol(input, &string, 10);
printf("Number: %ld String: '%s'\n", number, string);
// Number: 13 String: 'subdivision'
return 0;
}
https://repl.it/repls/SphericalImpracticalTinamou

Getting multiple strings as inputs

The Question is to take three names as input and check whether the 4th input is the first letter of one of those three names.
*It needs to be only of alpha type and no other.
Sample Input:
#ON SNOW
ARYA STARK
HODOR
#
Output:
NO
My code:
#include <stdio.h>
#include <ctype.h>
int main(){
char s1[100],s2[100],s3[100];
char ch[1];
scanf("%[^\n]s",s1);
scanf("%[^\n]s",s2);
scanf("%[^\n]s",s3);
scanf("%s",ch);
if(isalpha(ch[0]) && (s1[0]==ch[0] || s2[0]==ch[0] || s3[0]==ch[0]))
printf("yes");
else
printf("no");
}
As I figured out that gets() no longer works, I tried scanf("%s",s1);.
But since it does not store the calude after the whitespace " ", I tried this scanf("%[^\n]s",s1);. But the scanning stops at the first name itself.
John Player
NO
What is the way to store multiple strings in a char array without using loops and only using branching??
Now before getting to the specified problem lets see what the actual problem is:
Problem with scanf()
The problem with scanf() is that it is really bad at managing overflows. And in case of chars or char sequences the newline character is read on the press of enter key in the subsequent scanning. There are numerous instances on SO that concern this problem. scanf() leaves the new line char in buffer? and Problems with scanf
Problem with gets()
The biggest drawback is that here you need to know the size of input before-hand. If you know your input extremely well, you may use it (Still I won't recommend). Why is the gets function so dangerous that it should not be used?
Problem with fgets()
There are two really common problems with fgets()
The syntax of fgets() is:
char *fgets(char *restrict s, int n, FILE *restrict stream);`
and generally used like
fgets(char_array,100,stdin)
First problem arises when the input is bigger than the integer n provided in the fgets() second parameter. When the input in the buffer is bigger than n it will strip off 1st n chars and allocate it the char pointer which might be a char array. But what about remaining chars? They still are there in the input buffer and will be allocated to next fgets(). Messing things up.
Second problem is that every time a new line feed is allocated to the end of char sequence when the input is smaller than the int n-1.
But if we think for a while the problems with fgets() can be tackled with a simple trick.
Just check for the last character in the char sequence which has been recently allocated. If it is new line, replace it by NULL. Else we know that the input was more than that int provided inside fgets(). So all we have to do is eat up the remaining chars in the input buffer.
Here is an example:
char str1[5];
char str2[5];
fgets(str1,5,stdin);
if(strlen(str1)>0){//to avoid Undefined Behavior in case of null byte input
if(str1[strlen(str1)-1]=='\n'){
str1[strlen(str1)-1]='\0';
}
else{
while((getchar())!='\n');//eating the remaing chars in the buffer
}
}
fgets(str2,5,stdin);
if(strlen(str2)>0){
if(str2[strlen(str2)-1]=='\n'){
str2[strlen(str2)-1]='\0';
}
else{
while((getchar())!='\n');
}
}
printf("\n1.%s\n2.%s",str1,str2);
You could even convert strings you got using fgets to float and integers using things like strol or sscanf, but beware they may not show independent behavior.
Now coming back to the solution to your problem:
#include <stdio.h>
#include <string.h>
int main(){
char s1[100],s2[100],s3[100];
char ch[2];//make ch atleast 2 char wide
fgets(s1,100,stdin);
if(strlen(s1)>0){
if(s1[strlen(s1)-1]=='\n'){
s1[strlen(s1)-1]='\0';
}
else{
while((getchar())!='\n');
}
}
fgets(s2,100,stdin);
if(strlen(s2)>0){
if(s2[strlen(s2)-1]=='\n'){
s2[strlen(s2)-1]='\0';
}
else{
while((getchar())!='\n');
}
}
fgets(s3,100,stdin);
if(strlen(s3)>0){
if(s3[strlen(s3)-1]=='\n'){
s3[strlen(s3)-1]='\0';
}
else{
while((getchar())!='\n');
}
}
fgets(ch,2,stdin);
if(strlen(ch)>0){
if(ch[strlen(ch)-1]=='\n'){
ch[strlen(ch)-1]='\0';
}
else{
while((getchar())!='\n');
}
}
if(isalpha(ch[0]) && (s1[0]==ch[0] || s2[0]==ch[0] || s3[0]==ch[0]))
printf("yes");
else
printf("no");
return 0;
}
Try fgets.
fgets(s1,100,stdin);
fgets(s2,100,stdin);
fgets(s3,100,stdin);
#include <stdio.h>
int main(){
char s1[100],s2[100],s3[100];
char ch[1];
fgets(s1,100,stdin);// like gets but limited by length
fgets(s2,100,stdin);
fgets(s3,100,stdin);
scanf("%s",ch);
if( (s1[0]>='a' && s1[0]<='z') || (s1[0]>='A' && s1[0]<='Z') ){//ch-alpha?
if(s1[0] == ch[0]){ printf("yes"); }//s1[0] == ch[0] ??
else{ printf("no"); }
}
else
printf("no"); return 0; }

Array of "strings" in C

I know that there is a question with the same name, but it didn't work for me.
I'm making a home-compiler, returns the words that belongs to a language.
The words to analyze are in this vector:
char *cadenas[]= {"123", "4567L", "5a23", '\0'};
Now I want to enter the words by console, but strings can't be used in C, how can I do it? (Without making a matrix possibly)
void getCadenas(char *cadenas[]){
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
char cadena[15];
gets(cadena);
int x=0;
while(cadena[0]!='z'){
strcpy(cadenas[x],cadena);
x++;
gets(cadena);
}
}
If I understand your problem correctly, you would like the user to be able to enter multiple strings, until he/she types z
See if this piece of code helps you out. The strings will be stored in the cadenas array, as requested.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define MAX_CADENAS 100
#define MAX_CADENA_LEN 255
int getCadenas(char **cadenas){
int x=0;
char cad[MAX_CADENA_LEN+1];
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
while(x<MAX_CADENAS) {
scanf("%s", cad);
if (strcmp(cad,"z")==0)
break;
cadenas[x] = malloc(strlen(cad)+1);
strcpy(cadenas[x], cad);
x++;
}
return x;
}
char *cadenas[MAX_CADENAS];
int main() {
int num, i;
num = getCadenas(cadenas);
for (i=0;i<num; i++) {
printf("%s\n", cadenas[i]);
}
}
Note0: the code assumes you know in advance what the maximum number of input strings can be (100). It also assumes a maximum size for each input string (255 characters)
Note1: gets is deprecated. Also, instead of scanf, you might want to use fgets.
Note2: the present code is for illustrative purpose only. It allocates memory for each input string, but it assumes no error occurs in doing so (i.e. it does not check what malloc returns).
Note3: the allocated memory blocks must be freed when not used anymore (hint: cycle through the cadenas array and use free)
Assuming you don't mind carrying on with fixed-size strings and arrays, here is your original program modified:
#include <stdio.h>
#include <string.h>
#define MAX_CADENAS 100
#define CADENA_LIMIT 1000
// ...
void getCadenas(char cadenas[MAX_CADENAS][CADENA_LIMIT]){
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
int x;
for(x=0; x<MAX_CADENAS-1; x++){
char cadena[CADENA_LIMIT];
fgets(cadena, CADENA_LIMIT, stdin);
// fgets will copy the newline character, we don't want that
int cadenaLength=strlen(cadena);
if(cadena[cadenaLength-1]=='\n')
cadena[cadenaLength-1]='\0';
if(strcmp(cadena, "z")==0) break;
strcpy(cadenas[x], cadena);
}
cadenas[x][0]='\0';
}
// ...
Prefer fgets as you can prevent overflow of the fixed-size strings. Unfortunately it copies the newline as well, so I have code to handle that. The result is an array in the form you originally specified (except it ends with "" which we decided was what you were after in the comments).
You can read arbitrary sized strings in C like in other languages, but you would need to implement it with malloc() and co. Allocating dynamically sized memory is primarily controlled with the functions malloc, calloc, realloc and free. This would make the program unavoidably more complicated. Here is one way of doing this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ...
char *getCadena(){
int length=0, capacity=1, character;
char *cadena=malloc(1); // sizeof(char) is always 1
while((character=getchar())!=EOF){
if(character=='\n') break;
// Add character to string
length++;
if(capacity<length){
capacity*=2;
cadena=realloc(cadena,capacity);
}
cadena[length-1]=character;
}
// Add terminator to cadena
length++;
if(capacity<length){
capacity*=2;
cadena=realloc(cadena,capacity);
}
cadena[length-1]='\0';
return cadena;
}
char **getCadenas(){
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
int length=0, capacity=1;
char **cadenas=malloc(sizeof(char *));
for(;;){
char *cadena=getCadena();
if(strcmp(cadena,"z")==0){
free(cadena);
break;
}
// Add pointer to cadenas array
length++;
if(capacity<length){
capacity*=2;
cadenas=realloc(cadenas,capacity*sizeof(char *));
}
cadenas[length-1]=cadena;
}
// Add NULL to end of cadenas
length++;
if(capacity<length){
capacity*=2;
cadenas=realloc(cadenas,capacity*sizeof(char *));
}
cadenas[length-1]=NULL;
return cadenas;
}
void freeCadenas(char **cadenas){
int i=0;
while(cadenas[i]!=NULL){
free(cadenas[i]);
i++;
}
free(cadenas);
}
// ...
This works mostly the same as the previous function, except you should use freeCadenas eventually, and I end the array with NULL instead of "" which is customary.
The code is a lot longer, but it's pretty typical of more sophisticated C code with less arbitrary limits. In fact real C code usually has more robust handling of errors and more generic functions for managing dynamic arrays. If you actually manage to make this "home-compiler", however, you will figure all this out for yourself.

How to correctly input a string in C

I am currently learning C, and so I wanted to make a program that asks the user to input a string and to output the number of characters that were entered, the code compiles fine, when I enter just 1 character it does fine, but when I enter 2 or more characters, no matter what number of character I enter, it will always say there is just one character and crashes after that. This is my code and I can't figure out what is wrong.
int main(void)
{
int siz;
char i[] = "";
printf("Enter a string.\n");
scanf("%s", i);
siz = sizeof(i)/sizeof(char);
printf("%d", siz);
getch();
return 0;
}
I am currently learning to program, so if there is a way to do it using the same scanf() function I will appreciate that since I haven't learned how to use any other function and probably won't understand how it works.
Please, FORGET that scanf exists. The problem you are running into, whilst caused mostly by your understandable inexperience, will continue to BITE you even when you have experience - until you stop.
Here is why:
scanf will read the input, and put the result in the char buffer you provided. However, it will make no check to make sure there is enough space. If it needs more space than you provided, it will overwrite other memory locations - often with disastrous consequences.
A safer method uses fgets - this is a function that does broadly the same thing as scanf, but it will only read in as many characters as you created space for (or: as you say you created space for).
Other observation: sizeof can only evaluate the size known at compile time : the number of bytes taken by a primitive type (int, double, etc) or size of a fixed array (like int i[100];). It cannot be used to determine the size during the program (if the "size" is a thing that changes).
Your program would look like this:
#include <stdio.h>
#include <string.h>
#define BUFLEN 100 // your buffer length
int main(void) // <<< for correctness, include 'void'
{
int siz;
char i[BUFLEN]; // <<< now you have space for a 99 character string plus the '\0'
printf("Enter a string.\n");
fgets(i, BUFLEN, stdin); // read the input, copy the first BUFLEN characters to i
siz = sizeof(i)/sizeof(char); // it turns out that this will give you the answer BUFLEN
// probably not what you wanted. 'sizeof' gives size of array in
// this case, not size of string
// also not
siz = strlen(i) - 1; // strlen is a function that is declared in string.h
// it produces the string length
// subtract 1 if you don't want to count \n
printf("The string length is %d\n", siz); // don't just print the number, say what it is
// and end with a newline: \n
printf("hit <return> to exit program\n"); // tell user what to do next!
getc(stdin);
return 0;
}
I hope this helps.
update you asked the reasonable follow-up question: "how do I know the string was too long".
See this code snippet for inspiration:
#include <stdio.h>
#include <string.h>
#define N 50
int main(void) {
char a[N];
char *b;
printf("enter a string:\n");
b = fgets(a, N, stdin);
if(b == NULL) {
printf("an error occurred reading input!\n"); // can't think how this would happen...
return 0;
}
if (strlen(a) == N-1 && a[N-2] != '\n') { // used all space, didn't get to end of line
printf("string is too long!\n");
}
else {
printf("The string is %s which is %d characters long\n", a, strlen(a)-1); // all went according to plan
}
}
Remember that when you have space for N characters, the last character (at location N-1) must be a '\0' and since fgets includes the '\n' the largest string you can input is really N-2 characters long.
This line:
char i[] = "";
is equivalent to:
char i[1] = {'\0'};
The array i has only one element, the program crashes because of buffer overflow.
I suggest you using fgets() to replace scanf() like this:
#include <stdio.h>
#define MAX_LEN 1024
int main(void)
{
char line[MAX_LEN];
if (fgets(line, sizeof(line), stdin) != NULL)
printf("%zu\n", strlen(line) - 1);
return 0;
}
The length is decremented by 1 because fgets() would store the new line character at the end.
The problem is here:
char i[] = "";
You are essentially creating a char array with a size of 1 due to setting it equal to "";
Instead, use a buffer with a larger size:
char i[128]; /* You can also malloc space if you desire. */
scanf("%s", i);
See the link below to a similar question if you want to include spaces in your input string. There is also some good input there regarding scanf alternatives.
How do you allow spaces to be entered using scanf?
That's because char i[] = ""; is actually an one element array.
Strings in C are stored as the text which ends with \0 (char of value 0). You should use bigger buffer as others said, for example:
char i[100];
scanf("%s", i);
Then, when calculating length of this string you need to search for the \0 char.
int length = 0;
while (i[length] != '\0')
{
length++;
}
After running this code length contains length of the specified input.
You need to allocate space where it will put the input data. In your program, you can allocate space like:
char i[] = " ";
Which will be ok. But, using malloc is better. Check out the man pages.

Manipulation of lines of text

The below code tries to manipulate several lines of text one at the time.
1.My first issue is to write a loop to read several lines of text(using scanf()) and quit when the first character typed is a newline. These lines of text have some conditions: The first character must be a number between 2 and 6 followed by a space and a line of text(<80).This number will make "dance" the text.
2.My second issue is to figure out how to convert the letters from small to capital and viceversa according to the first number typed. I have to function to make these conversions but I don't know how to call them to change the text.For example: if I typed "3 apples and bananas" the correct output should be "AppLes And BanNas".As you see, the white spaces are ignored and the text always start with a capital letter.
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <ctype.h>
using namespace std;
void print_upper(string s1);
void print_lower(string s2);
void main(void)
{
char text[80];
text[0]='A';//Initialization
int count_rhythm;
while (text[0] != '\n'){//To make the loop run until a newline is typed
scanf(" %79[^\n]",text);
if(isdigit(text[0])) //To verify that the first character is a number
{
printf("\nGood");//Only to test
}
else
{
printf("\nWrong text\n");//Only to test
}
}
}
void print_upper(string s1)//Print capital letters
{
int k1;
for(k1=0; s1[k1]!='\0'; ++k1)
putchar(toupper(s1[k1]));
}
void print_lower(string s2)//Print small letters
{
int k2;
for(k2=0; s2[k2]='\0'; ++k2)
putchar(tolower(s2[k2]));
}
You could also define a function printNthUpper() which would take a string and and integer n that would specify which characters to print in upper case. The of the function would be a loop similar to the functions you already have, but with a conditional that compares the provided integer value and the index of a given letter to decide whether to
call toupper() (e.g. printf("%c", i%n == 0 ? toupper(s[i]) : s[i]);).
to write a loop to read several lines of text you can use condition based infinite loop in combination with fgets rather than using scanf.
char line[80];
char result[80]
while(1)
{
fgets(line,sizeof(line),stdin); //read line with fgets
puts(line);
if(line[0]=='\n')
break;
if((strlen(line)>=4) &&'2'< =line[0] && line[0] <= '6' && line[1]==' ')
{
strcpy(result,change_case_of_nth_char(line));// call change case of nth letter
}
else
{
//prompt user to enter input again
}
}
char *change_case_of_nth_char(char *str)
{
}

Resources