Manipulation of lines of text - c

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

Related

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

Compare a variable and a string

I am trying to code a C program to start specific functions on the OS X El Capitan.
The code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char mainchoice;
printf(">>> ");
scanf("%s", &mainchoice);
if (strcmp(&mainchoice, "start ftp") == 0) {
system("ftp");
}
else if (strcmp(&mainchoice, "start say") == 0) {
system("say hello");
}
else {
system("say Error")
}
}
This is just a sample code.
When I run it, it always says error via the say command. What am I doing wrong?
Focus here:-
char mainchoice; //declared as a char
scanf("%s", &mainchoice); //using the %s placeholder which is for string
//for character it is %c
Getting the logic behind your code is you want to enter a String not a character.
Make an array of characters like this:-
char mainchoice[20]; //this can hold your string, one character at one index each of the array
Since, your are using multi word in string comparison("start say")
(strcmp(&mainchoice, "start say") == 0)
scanf does not work for multi words. scanf stops reading from the keyboard as soon as you provide a whitespace, tabs, newline.
For solving that problem, use fgets. It's the best way to read multi words or even whole sentences. Never use gets()! It is vulnerable to buffer overflow!
fgets(mainchoice, 20, stdin);
you are declaring mainchoice as a character rather then a string.
use char mainchoice[10]; to create a string.
and replace scanf("%s",&mainchoice) with fgets(mainchoice, 10, stdin);
size is 10 because you are comparing it with a string of length 9, so(9+1 null=10) 10 are enough.

I have trouble with my answer in "Uva tex quotes" (trouble with spacing)

I'm trying to solve UVAa Online Judge Problem 272 — TeX Quotes.
Input will consist of several lines of text containing an even number of double-quote (") characters. Input is ended with an end-of-file character. The text must be output exactly as it was input except that:
the first " in each pair is replaced by two ` characters: `` and
the second " in each pair is replaced by two ' characters: ''.
I don't know why my code gives the wrong answer; I think it's the right answer.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
int main(){
char kalimat[100000];
int i;
int max;
bool flag=true;
while (scanf("%c",&kalimat)!=EOF){
max=strlen(kalimat);
for (i=0;i<=max;i++){
if (kalimat[i]=='"')
{
if (flag==true){
printf("``");
flag=false;
} else {
printf("''");
flag=true;
}
} else {
printf("%c",kalimat[i]);
}
}
}
return(0);
}
Note that scanf("%c",&kalimat) will read only 1 (one) character at a time. So strlen(kalimat) will always be 1. Not an actual problem, but just odd (e.g., you could declare char kalimat, instead of an char array, and not use indexing or the for loop).
Your for-loop, however, goes from 0 to max inclusive, thus kalimat will be indexed out-of-bounds, and result in undefined behaviour. Perhaps your problem is there.
In fact, since kalimat is a single character, it won't have a terminating '\0' character, and thus is not a valid C-string. Hence strlen can never compute the correct length (which is 1).
Try this:
char kalimat;
...
while (scanf("%c", kalimat) != EOF) {
if (kalimat == '"') {
if (flag){
printf("``");
flag = false;
} else {
printf("''");
flag = true;
}
} else {
printf("%c", kalimat);
}
}
}

Using atof() function in C with multiple input values

The goal of this program is to create a function which reads in a single string, user typed, command (ultimately for program to be used in conjunction with a robot) which consists of an unknown command word(stored and printed as command), and an unknown number of decimal parameters(the quantity is stored and printed as num, and the parameters are to be stored as float values in the array params). In the User input, the command and parameters will be separated by spaces. I believe my issue is with the atof function when I go to extract the decimal values from the string. What am I doing wrong? Thank you for the help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(char *input, char *command, int *num, float *params);
int main()
{
char input[40]={};
char command[40]={};
int num;
float params[10];
printf("Please enter your command: ");
gets(input);
func(input,command,&num,params);
printf("\n\nInput: %s",input);
printf("\nCommand: %s",command);
printf("\n# of parameters: %d",num);
printf("\nParameters: %f\n\n",params);
return 0;
}
void func(char *input, char *command, int *num, float *params)
{
int i=0, k=0, j=0, l=0;
int n=0;
while(input[i]!=32)
{
command[i]=input[i];
i++;
}
for (k=0; k<40;k++)
{
if ((input[k]==32)&&(input[k-1]!=32))
{
n++;
}
}
*num=n;
while (j<n)
{
for (l=0;l<40;l++)
{
if((input[l-1]==32)&&(input[l]!=32))
{
params[j]=atof(input[l]);
j++;
}
}
}
}
A Sample Output Screen:
Please enter your command: Move 10 -10
Input: Move 10 -10
Command: Move
# of parameters: 2
Parameters: 0.000000
The Parameters output should, ideally, read "10 -10" for the output. Thanks!
Change atof(input[l]) to atof(input + l). input[l] is single char but you want to get substring from l position. See also strtod() function.
Other people have already remarked the problem in your code, but may I suggest that you have a look at strtod() instead?
While both atof() and strtod() discard spaces at the start for you (so you don't need to do it manually), strtod() will point you to the end of the number, so that you know where to continue:
while(j < MAX_PARAMS) // avoid a buffer overflow via this check
{
params[j] = strtod(ptr, &end); // `end` is where your number ends
if(ptr == end) // if end == ptr, input wasn't a number (say, if there are none left)
break;
// input was a number, so ...
ptr = end; // continue at end for next iteration
j++; // increment number of params
}
Do note that the above solution does not differentiate between invalid arguments (say, foo instead of 3.5) and missing ones (because we've hit the last argument). You can check for that by doing this: if(!str[strspn(str, " \t\v\r\n\f")]) --- this checks if we're at the end of string (but allowing trailing whitespace). See the second side-note for what it does.
SIDE-NOTES:
You can use ' ' instead of 32 to check for space; this has two advantages:
It is clearer to the reader (it's very clear that it's a whitespace, instead of "some magic number that happens to have meaning")
It works in non-ASCII encodings (and the standard allows other encodings, though ASCII is by far the most popular; one common encoding is EBCDIC)
For future reference, this trick can help you skip whitespace: ptr += strspn(ptr, " \t\v\r\n\f");. strspn returns the number of characters at the start of the string that match the set (in this case, one of " \t\v\r\n"). Check documentation for more info.
Example for strspn: strspn("abbcbaa", "ab"); returns 3 because you have aab (which match) before c (which doesn't).
you are trying to convert a char into a float,
params[j]=atof(input[l]);
you should get the entire word(substring) of the float.
Example, "12.01" a null terminated string with 5 characters and pass it to atof, atof("12.01") and it will return a double of 12.01.
so, you should first extract the string for each float parameter and pass it to atof
Avoid comparing character to ascii value, rather you could have use ' ' (space) directly.
Instead of using for loop with a fixed size, you can use strlen() or strnlen() to find the length of the input string.

pangram function is not working in 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++]));}

Resources