I'm trying to read a string from stdin and substitute the vowels on the string by '_'.
Off course it's simple, but I want to substitute the accented vowels too. Obviously the following code doesn't work for those cases. I've tryied several things, like read char by char but and it to a short, consider the cases where line[i]<0, etc.
while(fgets(line, 250, stdin)){
size=strlen(line);
for(i=0;i<size;i++){
if(line[i]==65 || line[i]==69 ||line[i]==73 ||line[i]==79 ||line[i]==85 ||line[i]==97 ||line[i]==101 ||line[i]==105 ||line[i]==111 ||line[i]==117){
line[i]='_';
}
}
}
Any suggestions? Thank you in advance.
Ps: Consider the used encoding is Western (ISO-8859-1) -> http://www.alanwood.net/demos/ansi.html
You are probably running into a signed vs unsigned character issue. The ANSI values for the accented characters show on the link you provided are larger that the max size of an signed char. This is probably why you are seeing negative character values as well.
If you want to fix this properly, I'd suggest using a wide character format and character constants.
If you want something quick and easy, add the following in your for loop to see how the characters are mapping to values:
printf( "%c %d\n", line[i], (int)line[i] );
Then add the appropriate values to your if.
I used the following data
htyuàsdsècvcvcàdìssd
and the following code works with accented characters. The result was htyu_sds_cvcvc_d_ssd
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main(int argc, char **argv){
setlocale(LC_CTYPE, "UTF-8");
FILE *f = fopen("/Users/sandeepshabd/objectiveC/C_TEST_App/C_TEST_App/file.txt", "r, ccs=UTF-8");
if (!f)
return 1;
for (wchar_t c; (c = fgetwc(f)) != WEOF;){
switch (c) {
case L'à': c=L'_'; break;
case L'è': c=L'_';break;
case L'é': c=L'_';break;
case L'ì': c=L'_';break;
case L'ò': c=L'_';break;
case L'ù': c=L'_';break;
default: break;
}
wprintf(L"%c", c);
}
fclose(f);
return 0;
}
Related
I want to print out a polynomial expression in c but i don't know print x to the power of a number with printf
It's far from trivial unfortunately. You cannot achieve what you want with printf. You need wprintf. Furthermore, it's not trivial to translate between normal and superscript. You would like a function like this:
wchar_t digit_to_superscript(int d) {
wchar_t table[] = { // Unicode values
0x2070,
0x00B9, // Note that 1, 2 and 3 does not follow the pattern
0x00B2, // That's because those three were common in various
0x00B3, // extended ascii tables. The rest did not exist
0x2074, // before unicode
0x2075,
0x2076,
0x2077,
0x2078,
0x2079,
};
return table[d];
}
This function could of course be changed to handle other characters too, as long as they are supported. And you could also write more complete functions operating on complete strings.
But as I said, it's not trivial, and it cannot be done with simple format strings to printf, and not even to wprintf.
Here is a somewhat working example. It's usable, but it's very short because I have omitted all error checking and such. Shortest possible to be able to use a negative float number as exponent.
#include <wchar.h>
#include <locale.h>
wchar_t char_to_superscript(wchar_t c) {
wchar_t digit_table[] = {
0x2070, 0x00B9, 0x00B2, 0x00B3, 0x2074,
0x2075, 0x2076, 0x2077, 0x2078, 0x2079,
};
if(c >= '0' && c <= '9') return digit_table[c - '0'];
switch(c) {
case '.': return 0x22C5;
case '-': return 0x207B;
}
}
void number_to_superscript(wchar_t *dest, wchar_t *src) {
while(*src){
*dest = char_to_superscript(*src);
src++;
dest++;
}
dest++;
*dest = 0;
}
And a main function to demonstrate:
int main(void) {
setlocale(LC_CTYPE, "");
double x = -3.5;
wchar_t wstr[100], a[100];
swprintf(a, 100, L"%f", x);
wprintf(L"Number as a string: %ls\n", a);
number_to_superscript(wstr, a);
wprintf(L"Number as exponent: x%ls\n", wstr);
}
Output:
Number as a string: -3.500000
Number as exponent: x⁻³⋅⁵⁰⁰⁰⁰⁰
In order to make a complete translator, you would need something like this:
size_t superscript_index(wchar_t c) {
// Code
}
wchar_t to_superscript(wchar_t c) {
static wchar_t huge_table[] {
// Long list of values
};
return huge_table[superscript_index(c)];
}
Remember that this cannot be done for all characters. Only those whose counterpart exists as a superscript version.
Unfortunately, it is not possible to output formatted text with printf.
(Of course one could output HTML format, but this then would need to be fed into an interpreter first for correct display)
So you cannot print text in superscript format in the general case.
What you have found is the superscript 1 as a special character. However this is only possible with 1 and 2, if I remember correctly (and only for the right code-page, not in plain ASCII).
The common way to print "superscripts" is to use the x^2, x^3 syntax. This is commonly understood.
An alternative is provided by klutt's answer. If you switch to unicode by using wprintf instead of printf you could use all superscript characters from 0 to 9. Even though, I am not sure how multi-digit exponents look like in a fixed-width terminal it works in principle.
If you want to print superscript 1, you need to use unicode. You can combine unicode superscripts to write a multi-digit number.
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main() {
setlocale(LC_CTYPE, "");
wchar_t one = 0x00B9;
wchar_t two = 0x00B2;
wprintf(L"x%lc\n", one);
wprintf(L"x%lc%lc\n", one, two);
}
Output:
$ clang ~/lab/unicode.c
$ ./a.out
x¹
x¹²
Ref: https://www.compart.com/en/unicode/U+00B9
I am trying to compare two specific characters in two strings,but I want to make the comparing without case sensitivity. How can I do this?
right now I am using a code like that:
if (str1[i]==str2[j]) printf("Equal");
but I want to do this without case sensivity.
Thank you in advance for taking your time to help!
You can use low case for both chars, for example by using tolower function:
if (tolower(str1[i])==tolower(str2[j])) printf("Equal");
Also keep in mind: tolower does not work for multibyte char. So for those chars you should use other function
We can achieve your requirement by converting both of the character to either upper or lower case character using toupper() or tolower().
Example:
#include <stdio.h>
#include <ctype.h> //For tolower()
int main()
{
char str1[]="Time", str2[]="time";
/*
* Just for an example i am comparing the first char
* from 2 different strings.
*/
if(tolower(str1[0]) ==tolower(str2[0])) {
printf("Char's are equal\n");
}
else {
printf("Char's are not equal");
}
return 0;
}
Output:
Char's are equal
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; }
#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++]));}
when i execute that with 'é' it is accepted although the test! help!!
#include <stdio.h>
#include <string.h>
int main ()
{
char ch[10];
int i,k,k1;
do
{
k=0; i=0;
printf("Write a sentence without accentuated letters:\n");
scanf("%s",ch);
k1=strlen(ch);
while ((k==0)&&(i<k1))
{
if (ch[i]=='é') k=1;
i++;
}
}
while (k==1);
return 0;
}
The problem is probably with encoding. é can have different numerical representation depending on the encoding standard used. If your source code editor, compiler and your command line use different encodings, things will never work this way. You might want to switch to UTF-8.