Hi I want to write a program which takes a string and a number as input and then shifts the elements of string by given number, and also the string is always capital letters and the output should only be capital letters too
example 1 : -1 , "AB CD"
output 1 : "ZA BC"
example 2 : +3 , "ABC"
output 2 : "DEF"
I have written this code but if there is a space in my string , the program doesnt work properly
for example : -1 "AA AA"
the output is : "ZZ" But i was expecting "ZZ ZZ"
int main()
{
char str[100] = {NULL},y;
int n,x,i=0;
scanf_s("%d", &n);
scanf_s("%s", str);
while (str[i] != NULL) {
x = str[i];
if (x + n >= 65 && x + n <= 90) {
y = x + n;
str[i] = y;
}
else if (x + n < 65) {
while (x + n < 65) {
x += 26;
}
y = x + n;
str[i] = y;
}
else if (x + n > 90) {
while (x + n > 90) {
x -= 26;
}
y = x + n;
str[i] = y;
}
i++;
}
printf("%s", str);
return 0;
}
After reading non-whitespace, the scanf specifier %s stops when it encounters whitespace.
Instead of "%s", use " %99[^\n]" to:
read and ignore leading whitespace, then
read up to 99 characters, or until a newline character is encountered.
Reading at most 99 characters is important, as you must leave room in your buffer for the null-terminating byte, and not limiting the amount of data read can easily lead to buffer overflows.
The return value of scanf_s should be checked to ensure the expected number of conversions took place, before any data is used.
if (1 != scanf_s("%d", &n))
/* error! */;
Note that scanf_s requires a secondary argument when using %s or %[, which is the size of the buffer
char buf[10];
if (1 != scanf_s("%9s", buf, (rsize_t) sizeof buf))
/* error! */;
which is supposed to be of type rsize_t. If you are using the MSVC versions of these functions, this type is unsigned.
Due to the pitfalls involved with using scanf properly, and the portability issues of scanf_s, consider instead using fgets to read lines of input (and strtol to parse an integer).
For clarity, consider using character constants like 'A' and 'Z', instead of integer constants like 65 and 90.
As is, your current code does not account for non-alphabetic characters, and will shift those. Consider the use of isalpha or isupper to filter the application of the shift.
Note NULL is usually considered a pointer value. Use '\0', or just 0, to represent the null-terminating byte.
Related
Here's the exact question:
Write a C program that takes a character as input and prints the alphanumeric character (0-9, A-Z, a-z are alphanumeric characters) that is closest to this character. NOTE: If the input character is equidistant from two alpha-numeric values, either one can be printed.
I know we would have to use the ASCII table and make some cases but I can't figure out how to exactly do it.
Yes, the solution relies on ASCII values. You can simply use an if-else-if ladder to figure out the closest alphanumeric character to the input character. If the input is already an alphanumeric character, you can use the built-in isalpha and isdigit functions to quickly arrive at the solution. If it is not then make use of either of the comparison operators < or >, and figure out in which end of these ranges 0-9, A-Z, a-z your solution lies in.
The order in which you make the comparisons is important in order to reduce the number of comparisons. Here is the ASCII Table for reference.
Since you are new to this site, take my code and learn from it. But you may not always get your solution in the form of complete code over here.
#include <stdio.h>
#include <ctype.h>
int main()
{
unsigned char input, tmp, result;
printf("Enter the input character: ");
scanf("%c", &input);
if (isalpha(input))
{
tmp = input - 1;
result = isalpha(tmp) ? tmp : input + 1;
}
else if (isdigit(input))
{
tmp = input - 1;
result = isdigit(tmp) ? tmp : input + 1;
}
else if (input < '0')
{
result = '0';
}
else if (input > '9' && input < 'A')
{
result = (input - '9' > 'A' - input) ? 'A' : '9';
}
else if (input > 'Z' && input < 'a')
{
result = (input - 'Z' > 'a' - input) ? 'a' : 'Z';
}
else
{
result = 'z';
}
printf("Alphanumeric character closest to '%c' is '%c'", input, result);
return 0;
}
I need to compare strings comparing letters and numbers just by letters and appearance of a number in C.
For example strings "first%dsecond%dj" should be considered equal to any string like "first[number]second[number]j".
I tried to do that like this:
char *c_i
int i, j;
if (sscanf(c_i, "first%dsecond%dj", &i, &j) == 2 &&
c_i[strlen(in) - 2] == 'j') {
printf("%s", c_i);
}
but sscanf ignores everything behind the last number so strings like "first%dsecond%dthird%dj" also give the true value and is printed.
Generally sscanf cares just about the values of letters before the last specifier and I would like to find something that counts also the letters after, like say a comparer that checks the whole strings and gets any number but number.
Of course I can do that by creating my own char* scanner, but I would like to avoid this if there is a simpler way.
Use %n to get the length of the conversion, then check that the string really ends there:
void checkString(const char *s)
{
int i, j, n = 0;
if (sscanf(s, "first%dsecond%dj%n", &i, &j, &n) == 2 && s[n] == '\0')
{
printf("%s", s);
}
}
Variation on #unwind's good answer.
Use "%n" to record the current position in the scan and "*" to negate the need for saving to an int.
n ... The corresponding argument shall be a pointer to signed integer into which is to be written the number of characters read from the input stream so far by this call to the fscanf function. ... C11 §7.21.6.2 12
An optional assignment-suppressing character *. §7.21.6.2 3
// return true on match
bool IE_compare(const char *c_i) {
int n = 0;
sscanf(c_i, "first%*dsecond%*dj%n", &n);
return n > 0 && c_i[n] == '\0';
}
Note: The format string can be coded as separate sting literals for alternative reading.
sscanf(c_i, "first" "%*d" "second" "%*d" "j" "%n", &n);
The above will match leading spaces before the number like "first +123second -456j" as "%d" allows that. To avoid:
int n1, n2,
int n = 0;
sscanf(c_i, "first%n%*dsecond%n%*dj%n", &n1, &n2, &n);
return n > 0 && !isspace((unsigned char) c_i[n1]) &&
!isspace((unsigned char) c_i[n2]) && c_i[n] == '\0';
The above will match numbers with a leading sign like "first+123second-456j" as "%d" allows that. To avoid:
sscanf(c_i, "first%n%*dsecond%n%*dj%n", &n1, &n2, &n);
return n > 0 && isdigit((unsigned char) c_i[n1]) &&
isdigit((unsigned char) c_i[n2]) && c_i[n] == '\0';
// or
int n = 0;
sscanf(c_i, "first%*[0-9]second%*[0-9]j%n", &n);
return n > 0 && c_i[n] == '\0';
What remains somewhat unclear is if the occurrence of a number is required. "...and appearance of a number" implies yes. Should "firstsecondj" match? The above answers assume no.
I am doing homework to school. Task is to make program in C that can do some simple things with matrixes like *, -, +.
My program is reading matrixes and save them to int array. When the matrix input ended, I scanf to char to know what operation iam going to do with the matrixes. Operation are stores in char array. (on input can be up to 100 matrixes so 99 operations in between). If user writes * everything is okay, BUT when user writes '-' or '+' it stores '/n'. I was googling and debuging but still dont know why this happens. Any suggustions are welcome.
User input looks like this: First line is size of matrix.
2 3
76 98 -31
30 30 32
-
2 3
89 25 38
1 -32 -38
int* readMatrix(int width, int height, char arrayOperation[], int numberOfMatrix, int*err)
{
int sizeOfMatrix = ((height*width) + 3), i = 0;
char operation = 'n';
int *arrayMatrix = malloc(sizeOfMatrix* sizeof(int));
arrayMatrix[0] = width;
arrayMatrix[1] = height;
for (i = 2; i <= sizeOfMatrix; i++)
{
if (i == sizeOfMatrix)
{
if (scanf_s("%c", &operation) != EOF)
{
if (operation == '*' || operation == '-' || operation == '+')
{
arrayOperation[numberOfMatrix] = operation;
}
else
{
*err = 100;
}
}
else
{
arrayOperation[numberOfMatrix] = 'n';
break;
}
}
else if (scanf_s("%d", &(arrayMatrix[i])) == 1)
{
*err = 0;
}
}
return arrayMatrix;
}
In case of * the var operation==*,but in -,+ operation==/n. I call this function in loop, output array is stored in array of int**.
scanf("%c" reads the very next character without skipping any whitespace, so it will store whatever is after the last thing read -- usually a newline. If you want to skip whitespace, add a space to the format:
scanf(" %c", &operation)
this will skip any whitespace and store the next non-whitespace character.
You don't need this with %d as all of the conversion patterns except %c and %[ skip whitespace.
I was discusing this particular problem with my lecturer.
I understand this: when scanf reading the number it jumps over whitespace and /n.
So reading "32/n - " results in reading everything. When reading "32/n * " it stops at "*" because its not sign of any number. So its behave little stupid.
This can solve using fgets() function and read it by char.
The task is: a user types an char array and the programm stops when the last two values make a match with the first and second inserted values, then it prints only inserted int values.
For example, I type: 1,2,f,5,2,g,s,d,c,3,1,2
And get 1,2,5,3
This what I've got for now
int main()
{
setlocale(LC_ALL, "RUS");
char* A;
int i = 2, N;
//making an array
A = (char*)malloc(2 * sizeof(char));
printf("Enter an array \n");
//entering the first value
scanf_s("%c", &A[0]);
//second value
scanf_s("%c", &A[1]);
//next values
while (!(A[i - 1] == A[0] && A[i] == A[1]))
{
i++;
A = (char*)realloc(A, (i + 1)*sizeof(char));
scanf_s("%c", &A[i]);
}
system("pause");
return 0;
}
So now it makes a stop only if the first value makes a match and prints nothing. I am really confused
You can avoid dynamically allocating altogether and just focus on the logic of your task. While you can use scanf for reading character input, you are better served using a character-oriented input function such as getchar.
That said, it appears you want to read characters from stdin, only storing unique digits in your array, and then if the user enters digits that match your first two elements stored in your array, print the values stored in the array and exit. (If I have any of that wrong, please let me know in a comment)
First off, reading characters with scanf can be a bit finicky depending on the values separating the character. However since you are only concerned with storing digits, that makes things a bit easier.
To avoid dealing with malloc, just set some reasonable limit to size your array and check your stored elements against. A simple #define is all you need. For example:
#define MAXE 128
Will define a constant MAXE (for max elements), to test against as you fill your array. Just keep a count of the elements you add to the array, and if you reach your limit, exit.
You want to keep reading characters until one of two conditions are met: (1) you have added 128 values to your array with no exit condition tripped, or (2) the last two characters entered match the digits store in a[0] and a[1]. To set up your read you can do something like:
while (n < MAXE && scanf ("%c", &c) == 1) { ...
note: with getchar() you can avoid the non-portable _s function issue, among other pitfalls with the scanf family of functions. The changes are minimal to use getchar() instead of declaring c as type char, declare c as type int, and then change your assignment to c as follows:
while (n < MAXE && (c = getchar()) != EOF) {
After reading a character, (regardless of how), you want to test whether it is a digit, if not you are not storing it and it can't be part of your exit condition. So you can simply get the next char if it isn't a digit:
if (c < '0' || '9' < c)
continue;
(note: ctype.h provides the isdigit() function that can be used instead of the manual checks)
You want to store the first two digit regardless, and following those two, you want to store any new digits entered (not already stored), so you need to test the current digit against all digits previously stored to insure it is a unique digit. While you can code the logic several ways, in this case your test loop must test all values stored before making a decision to store the current digit. In this situation, and in situations where you need to break control within nested loop, the lowly goto statement is your best friend. Here if the digit is a duplicate, the goto simply skips to the dupes label passing over the assignment:
if (n > 1)
for (i = 0; i < n; i++)
if (c == a[i])
goto dupe;
a[n++] = c;
dupe:;
The last part of the puzzle is your exit condition. This is a bit tricky (but simply solved) because you know you will not store the preceding (or for Leffler, the penultimate) value in the array to test against (it being non-unique to the array). The trick is just to save the character from the last iteration to test against. (maybe in a variable called last). Now you can code your exit clause:
if (n > 2 && a[0] == last && a[1] == c)
break;
Putting it all together, you could do something like the following:
#include <stdio.h>
#define MAXE 128
int main (void) {
char a[MAXE] = "", c, last = 'a';
int i, n = 0;
printf ("Enter an array\n");
while (n < MAXE && scanf ("%c", &c) == 1) {
if (c < '0' || '9' < c)
continue;
if (n > 1)
for (i = 0; i < n; i++)
if (c == a[i])
goto dupe;
a[n++] = c;
dupe:;
if (n > 2 && a[0] == last && a[1] == c)
break;
last = c;
}
if (n < 3) {
fprintf (stderr, "error: minimum of 3 values required.\n");
return 1;
}
if (n == MAXE) {
fprintf (stderr, "warning: limit of values reached.\n");
return 1;
}
printf ("Values in array: ");
for (i = 0; i < n; i++)
putchar (a[i]);
putchar ('\n');
return 0;
}
How you handle the printing and error conditions are up to you. Those included above are just a thought on how you could cover your bases.
Note: gcc does not implement the optional _s functions, so you can make the change back to scanf_s if you need to.
Example Use/Output
$ ./bin/exitonmatch
Enter an array
1
2
f
5
2
g
s
d
c
3
1
2
Values in array: 1253
Look it over and let me know if you have any questions.
Accept Any Char as Termination/Store only Unique Digits
If the logic as you have explained, is to track the first two characters, regardless of whether they are digits and allow any character to serve as the termination check of first two entered sequence, the easiest way to handle that is to simply store the first two characters entered in a separate array (or two variables) and check each sequence of characters entered against them.
Adding this type check takes no more than a slight rearranging of the conditions in the original to allow a few checks on any character entered before considering only digits for storage in your array.
note: the cc (character count) variable was added to track the number of characters entered and the first array was added to hold the first two characters entered.
For example:
char a[MAXE] = "", first[TSTA] = "", last = 'a';
int c, cc = 0, i, n = 0;
printf ("Enter an array\n");
while (n < MAXE && (c = getchar()) != EOF) {
if (c < ' ') continue; /* skip non-print chars */
if (cc < 2) /* fill first[0] & [1] */
first[cc] = c; /* check term condition */
if (++cc > 2 && first[0] == last && first[1] == c)
break;
last = c; /* set last */
if (c < '0' || '9' < c) /* store only numbers */
continue;
if (n > 1) /* skip duplicates */
for (i = 0; i < n; i++)
if (c == a[i])
goto dupe;
a[n++] = c; /* digit and not a dupe - store it */
dupe:;
}
note: getchar is used above, but you can substitute scanf from the first example if you like.
Example Use/Output
Here there first two characters are a and b which serve as the termination sequence despite not being digits.
$ ./bin/exitonmatchgc
Enter an array
a
b
c
4
5
g
h
4
9
3
b
a
b
Values in array: 4593
I'm making a program in which i ask for the username name, and i'd like to only accept strings with valid characters only (alphabetic).
I found that i can either use
do{
//since scanf returns the number of currectly input
if(scanf("%s", &name) == 1)
break;
else printf("Please enter a valid name.\n);
}while(1);
or
do{
check = 0;
scanf("%s", &name);
for(i=0; i<strlen(name; i++){
//since isalpha() returns != 0 if it's a letter
if(isalpha(name[i]) == 0){
printf("Invalid character. Please enter a valid name.\n");
check = 1;
break;
}
}
}while(check == 1);
But i'm not sure if any of those work, and what would be better to check if there isn't anything except alphabetic letters.
Also though about making all input letters (after this verification) on lower case and make the first letter upper case with
//all to lower except the first letter
for(i=1; i<strlen(name); i++){
name[i] = tolower(name[i]);
}
//first letter to upper
name[0] = toupper(name[i]);
x=1;
while(name[x] != '\0'){
//if the letter before is a white space, even the first letter, it should place the first letter of a name upper
if(name[x-1] == ' ')
name[x] = toupper(name[x]);
x++;
}
Would this work?
if(scanf("%s", &name) reads in all non-white-space, not just letters, into name and does not return if input is only "\n".
if(isalpha(name[i]) == 0){ loop is not bad, but scanf("%s", &name) still does not return if input is only "\n" or just white-space.
for(i=1; i<strlen(name); i++) name[i] = tolower(name[i]) works to make all following letters lower case, but if inefficient as code repeatedly calculates the string length.
Separate reading data and parsing data. Use fgets() to read the data and various code to test the data for correctness.
char buf[200];
fgets(buf, sizeof buf, stdin);
int n = 0;
// Skip leading white-space
// Look for A-Z, a-z or space (like a space between first & last)
// Skip white-space like \n
// Save into 'n' the current scan position
sscanf(buf, " %*[A-Za-z ] %n", &n);
if (n > 0 && buf[n] == '\0') Success(); // #user3121023
Should code need to rid buf of a potential trailing "\n", suggest:
buf[strcspn(buf, "\n")] = 0;
Let's look at each option.
First option:
do {
//since scanf returns the number of currectly input
if(scanf("%s", &name) == 1)
break;
else printf("Please enter a valid name.\n");
} while(1);
This won't quite work the way you expect. First off, what exactly is name? I'm almost sure that you want scanf("%s", name) instead (name instead of &name), unless you declared it as char name;, which would be catastrophic anyway.
Anyway, the problem I see with this approach is that you don't really validate the string. Read the man page section about %s:
s - Matches a sequence of non-white-space characters; the next pointer
must be a pointer to character array that is long enough to hold
the input sequence and the terminating null byte ('\0'), which is
added automatically. The input string stops at white space or at the
maximum field width, whichever occurs first.
Nothing says that the string is composed of alphabetic characters only.
Second option:
do{
check = 0;
scanf("%s", &name);
for(i=0; i<strlen(name); i++){
//since isalpha() returns != 0 if it's a letter
if(isalpha(name[i]) == 0){
printf("Invalid character. Please enter a valid name.\n");
check = 1;
break;
}
}
}while(check == 1);
Again, you probably want name rather than &name. You also shouldn't be calling strlen() in the for loop condition, because it's inefficient (strlen() is O(n)). A smart compiler may optimize it away, but it's hard for the compiler to know when it is safe to do so. Just call strlen() before the loop and store the result in a variable.
isalpha() expects an integer as an argument, which is expected to be either EOF or an unsigned char converted to int. Again, you don't show the declaration for name, but assuming that it is a character array, you should cast name[i] to unsigned char before calling isalpha(), so that you don't get any sign extension surprises:
if (isalpha((unsigned char) name[i]) == 0) { /* ... */ }
In fact, gcc nowadays will most likely give you a warning if you call any of the ctype family macros / functions with a plain char. The macros are deliberately written in such a way that a warning is shown, precisely because this is a common mistake. It is implementation-defined whether a plain char is signed or unsigned. You would get problems in a platform with signed chars because of sign extension (this is because typically, things like isalpha() are implemented using lookup tables, and extending the sign yields a negative number that would index the lookup table with a negative index - Oops!)
Other than this, this approach seems ok to me.
A third, maybe better option:
Since you mentioned fgets(), I think you could do this easily by combining fgets() with sscanf(). First, you read a line with fgets(). Then, you use sscanf() to match a string consisting of only characters in the range [a-zA-Z]. This can be done with the format specifier %[a-zA-Z]s. Then, you just have to check if this matched the entire line. Here's a working program:
#include <stdio.h>
#include <string.h>
int main(void) {
static char buf[512];
static char name[512];
int is_valid = 0;
while (!is_valid) {
fgets(buf, sizeof(buf), stdin);
size_t line_len = strlen(buf);
if (line_len > 0 && buf[line_len-1] == '\n') {
buf[line_len-1] = '\0';
line_len--;
}
int n = 0;
if (sscanf(buf, " %[a-zA-Z] %n", name, &n) == 1 && buf[n] == '\0') {
is_valid = 1;
} else {
printf("Please enter a valid name.\n");
}
}
printf("Name: %s\n", buf);
return 0;
}
Make sure your buffers are large enough; this code is vulnerable to buffer overflow for arbitrarily long names / lines.
Now let's see the code to make the first letter upper case:
//all to lower except the first letter
for(i=1; i<strlen(name); i++){
name[i] = tolower(name[i]);
}
//first letter to upper
name[0] = toupper(name[i]);
x=1;
while(name[x] != '\0'){
//if the letter before is a white space, even the first letter, it should place the first letter of a name upper
if(name[x-1] == ' ')
name[x] = toupper(name[x]);
x++;
}
Again, remove strlen() from the loop condition. toupper() and tolower() also expect an int as an argument representing either EOF or an unsigned char converted to int. You should cast it to unsigned char to avoid problems with possible sign extension, as I said earlier with the other example.
This is wrong:
//first letter to upper
name[0] = toupper(name[i]);
It should be:
//first letter to upper
name[0] = toupper(name[0]);
(The argument to toupper() is name[0], not name[i]).
Finally, this is useless:
x=1;
while(name[x] != '\0'){
//if the letter before is a white space, even the first letter, it should place the first letter of a name upper
if(name[x-1] == ' ')
name[x] = toupper(name[x]);
x++;
}
%s will never give you a string with whitespaces (refer to the manpage quote I pasted above).
Assuming that you want your name to have only characters a through z or A through Z then you could use this function
//Returns 1 if non alphabetic character is found, 0 otherwise
int NonAlphaCharsFound(char *name)
{
int FoundNonChar = 0;
int i, nameLength;
nameLength = strlen(name);
for(i = 0; i < nameLength; i++)
{
if((name[i] >= 'a' && name[i] <= 'z') || (name[i] >= 'A' && name[i] <= 'Z') || name[i] == ' ')
{
//do nothing if it's an alphabect character
//name[i] == ' ' is to allow for spaces if you want spaces in the name
}
else
{
FoundNonChar = 1;
break;
}
}
return FoundNonChar;
}