Add a number to an ascii string in C language - c

I have a string in C and I need to add +1 to every character in the string. For example, I want abc def to become bcd efg. I want to run it as abc def | ./myprog
This is the code I have, and I can't seem to figure out what the problem is:
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]) {
char stringline[200];
char result[200];
int lengthofstr;
int i;
scanf("%s", &stringline);
lengthofstr = strlen(stringline);
for(i=0; i < stringline; i++) {
stringline[i] = (stringline[i] + 1);
}
printf("%s", stringline);
return 0;
}

Looks like a typical typo. Replace
for(i=0;i<stringline;i++){
with
for(i=0;i<lengthofstr;i++){

Compare with the length of the string, not with the array itself
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]){
char stringline[200];
int lengthofstr;
int i;
scanf("%199s", &stringline);
lengthofstr = strlen(stringline);
for(i=0;i<lengthofstr;i++){ // Modify HERE
stringline[i] = (stringline[i] + 1);
}
printf("%s", stringline);
return 0;
}
You were comparing with a pointer which will always be true

Rather than complicating the logic with scanf and format specifiers, etc., you could just read a character at a time from stdin and add '1' if it is an alphabetical character. Try:
#include <stdio.h>
#define MAXC 200
int main (void) {
int c;
int idx = 0;
char result[MAXC] = {0};
while ((c = getchar()) != '\n' && c != EOF && idx < MAXC) {
if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) c++;
result[idx++] = c;
}
printf ("\n result: %s\n\n", result);
return 0;
}
Output
$ echo "abc def" | ./bin/stdinplus1
result: bcd efg
It also has the added benefit of leaving non A-Za-z characters unchanged:
$ echo "abc/def*g = hij" | ./bin/stdinplus1
result: bcd/efg*h = ijk

Related

counting the number of letter occurences in an Array

I want a code that counts the number of occurrences of letters in an array. I have looked at various codes that do the exact, but they all use strings. My issue here is to strictly use arrays.
I have created a code, but it returns: : 0 : 1 : 2 : 3 : 4 : 5 : 6 : 7 : ...
one correct example:
input:
The quick brown fox jumps over the lazy dog.
output:
A: 1
B: 1
C: 1
D: 1
E: 3
F: 1 ...
The following is my code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
int i = 0;
int c;
char counts[26] = {0};
c = getchar();
while (c != EOF && i < 26) {
counts[i] = c;
i += 1;
c = getchar();
}
for (i = 0; i < 26; i++) {
if (counts[i] !=0 )
printf("%c: %d", toupper(c), i);
}
return EXIT_SUCCESS;
}
Using your code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
int c;
int counts['Z' - 'A'] = {0};
c = getchar();
while (c != EOF)
{
if (isalpha(c))
counts[(toupper(c)-'A')]++;
c = getchar();
}
for (unsigned int i = 0; i < sizeof(counts)/sizeof(counts[0]); i++)
{
if (counts[i] !=0 )
printf("%c: %d\n", 'A'+i, counts[i]);
}
return EXIT_SUCCESS;
}
Your array is designed to store occurencies of each letter. So the idex of an array must be the latter entered. As you can see I used (toupper(c)-'A') that makes the value of entered char 0 based index.
You must check that entered char is an alphabet char. if (isalpha(c)) do that.
The printout must print characters using the index of array and array content

Function to identify upper/lower case letters C

I'm trying to create a function that will identify whether the first letter input is upper or lower case then output the rest of the string in that same case(upper/lower).
For example, "Hi there" would become "HI THERE".
I'm not familiar with fgets. Once I run it I can input and press enter and the program doesn't run. I'm not getting any compiler errors. I believe I went wrong in the void shift function.
Also, I know gets is not recommended, is fgets similar? Or is it better to use scanf?
#include <stdio.h>
#include <ctype.h>
void shift (char *my_string); // Function declaration
int main()
{
char inputstring[50];
printf("Enter a string\n");
char *my_string = inputstring;
shift(my_string); // Function
}
void shift (char *my_string) // Function definition
{
int i =0;
char ch;
for(i=0; i<50; i++)
fgets(my_string, 50, stdin);
while(my_string[i])
{
if(ch>='A' && ch<= 'Z') // When first char is uppercase
{
putchar (toupper(my_string[i]));
i++;
}
else if (ch>='a' && ch <= 'z') // When first char is lowercase
{
putchar(tolower(my_string[i]));
i++
}
}
return;
}
You don't need to call fgets() fifty times. It reads a line from stdin and writes it to my_string. It seems you only want to read one line, not fifty (and keep only the last one). The 50 is the maximum number of characters (minus one) that will be read and written to the buffer. This limit is to prevent buffer overflow. See fgets().
Try removing the for loop on the line before the fgets() call. Also, you don't need the my_string in main(). The corrected code:
#include <stdio.h>
#include <ctype.h>
void shift (char *my_string);//function declaration
int main()
{
char inputstring[50];
printf("Enter a string\n");
shift(inputstring);
}
void shift (char *my_string) //function definition
{
int i;
char ch;
if ( fgets(my_string, 50, stdin) == NULL )
return;
ch = my_string[0];
for ( i=0; my_string[i]; i++ )
{
if(ch>='A' && ch<= 'Z') //when first char is uppercase
{
putchar (toupper(my_string[i]));
}
else if (ch>='a' && ch <= 'z')//when first char is lowercase
{
putchar(tolower(my_string[i]));
}
}
return;
}
Edit: Added ch initialization, pointed out by #thurizas. Changed while loop to for loop. Added check to return value of fgets() as suggested by #JonathanLeffler. (See his comment about the buffer size.)
Here is another solution for your problem,
#include <stdio.h>
#include <ctype.h>
void convertTo (char *string);
int main()
{
char inputString[50];
printf("Enter a string\n");
convertTo(inputString);
}
void convertTo (char *string)
{
int i;
char ch;
gets(string);
ch = string[0];
for ( i=0; string[i]; i++ )
{
if(ch>='A' && ch<= 'Z')
{
if(string[i]>='a' && string[i]<= 'z')
string[i] = string[i] - 32;
}
else if (ch>='a' && ch <= 'z')
{
if(string[i]>='A' && string[i]<= 'Z')
string[i] = string[i] + 32;
}
}
printf("%s\n", string);
return;
}
All ASCII characters are represented by 7-bits. (thus the term 7-bit ASCII) The only bitwise difference between lower-case and upper-case is that bit-5 (the sixth bit) is set for lowercase and cleared (unset) for uppercase. This allows a simple bitwise conversion between lowercase and uppercase (either by adding/subtracting 32 or by simply flipping bit-5 directly.)
+-- lowercase bit
|
a = 01100001 A = 01000001
b = 01100010 B = 01000010
c = 01100011 C = 01000011
...
This allows a simple test and conversion if the first character is upper-case:
#include <stdio.h>
enum { MAXC = 50 };
char *shift (char *my_string);
int main (void)
{
char inputstring[MAXC] = {0};;
printf ("\n Enter a string: ");
if (shift (inputstring))
printf (" my_string is : %s\n", inputstring);
return 0;
}
char *shift (char *my_string)
{
char *p;
if (!(p = fgets (my_string, MAXC, stdin))) return NULL;
if (*p == '\n') return NULL; /* Enter only pressed */
if ('A' <= *p && *p <= 'Z') /* test for upper case */
for (; *p; p++) /* convert lower/upper */
if ('a' <= *p && *p <= 'z') *p &= ~(1 << 5);
return my_string;
}
Example Use
$ ./bin/case_1st_to_upper
Enter a string: this is my string
my_string is : this is my string
$ ./bin/case_1st_to_upper
Enter a string: This is my string
my_string is : THIS IS MY STRING

Vigenere Cipher only works up until dealing with a space(" ") in C - why?

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, string argv[])
{
string k = argv[1];
string s = GetString();
int l = strlen(k);
for(int i = 0, n = strlen(s); i < n; i++)
{
if(s[i] >= 65 && s[i] <= 90)
{
int i2 = ((s[i]-65) + (k[i%l]-97)) % 26;
printf("%c", i2+65);
} else if(s[i] >= 97 && s[i] <= 122)
{
int i2 = ((s[i]-97) + (k[i%l]-97)) % 26;
printf("%c", i2+97);
} else
{
printf("%c", s[i]);
}
}
printf("\n");
return 0;
}
I have removed as many parts as I can in order to make the code more relevant to the question. Basically why does this code work when "s" does not have any space(" ") in it and doesn't when "s" consists of space(" ")?
As most of you may know the idea is the argument entered at argv[1] is the "keyword" for the cipher. User then inputs a "plain-text" to cipher (s). It works when I try with various words or sentences if it doesn't include any space, " ". I just don't understand the logic behind this. Why does the cycle break if s[i] is not one of the first two conditions - I would have thought that "else" condition would work.
I would really appreciate it if someone can shed some light on this - many thanks in advance!
ps: I know there are some extra libraries at the top and the user input at argv[1] is not verified via isalpha(). I just want to understand the cycle process better for now, I have those checks in another file ready.
Here is code that implements the 'separate counters for string and key' comment that I made. It also uses the letter codes 'a' and 'A' (and avoids needing to use 'z' or 'Z') instead of using numbers. It does assume that you are dealing with a single-byte code set (not UTF-8 unless you're working in the ASCII range) where the lower-case and upper-case letters are each in a contiguous range (so it won't work reliably with EBCDIC, but will with most other code sets), and it also ignores accented characters. (It would have to do setlocale("") to get locale-specific interpretations of which characters are letters.)
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s key\n", argv[0]);
return 1;
}
string k = argv[1];
int l = strlen(k);
for (int i = 0; i < l; i++)
{
int c = k[i];
if (!isalpha(c))
{
fprintf(stderr, "%s: non-alpha character %c in key string\n", argv[0], c);
return 1;
}
k[i] = tolower(c);
}
printf("Enter a string to be encrypted:\n");
string s = GetString();
int n = strlen(s);
for (int i = 0, j = 0; i < n; i++)
{
int c = (unsigned char)s[i];
if (isupper(c))
c = ((c - 'A') + (k[j++ % l] - 'a')) % 26 + 'A';
else if (islower(c))
c = ((c - 'a') + (k[j++ % l] - 'a')) % 26 + 'a';
putchar(c);
}
putchar('\n');
return 0;
}
Here is a sample run that demonstrates the weakness of using 'a' as one of the letters in the key for this Vigenere cipher:
./vc caesArandAbrAcaDabRa
Enter a string to be encrypted:
It is reported that Caesar said "Veni, vidi, vici" when he conquered Britain.
Kt mk rvpbutfu tjaw Cbvscr wsiu "Vrqi, wzdk, vlcj" nhgn lw cfndxesvd Drltbzn.

Fixing a letter frequency analyser in C

I'm new to programming and I need some help in getting my program to work because I am kind of stuck at the moment. It's suppose to count the frequency of a letter and other characters for an input text file then print out the results but nothing happens when I do insert a file (but it does compile). This is what I have so far. I think its because I don't return the results of the array back into the main function so it can print out, but I am not sure how to do this. Would you need to use malloc (e.g. int *alphabetCount = (int *)malloc(sizeof(int)*ALPHABET_SIZE);) for the array then free it later?
Any help would be appreciated!
#include <stdio.h>
#include <stdlib.h>
#define ALPHABET_SIZE 26
#define FIRST_LC_LETTER 'a'
#define LAST_LC_LETTER 'z'
#define FIRST_UC_LETTER 'A'
#define LAST_UC_LETTER 'Z'
int freqAnalysis (int inputChar);
int main (int argc, char *argv[]) {
int inputChar = getchar();
int position = 0;
char alphabet [ALPHABET_SIZE] = {'a','b','c','d','e','f','g','h','i','j',
'k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int alphabetCount [ALPHABET_SIZE];
freqAnalysis (inputChar);
while (position < ALPHABET_SIZE) {
printf ("Letter %c: %d\n",alphabet[position],alphabetCount[position]);
position++;
}
return EXIT_SUCCESS;
}
int freqAnalysis (int inputChar) {
int counter;
int numbers;
int spaces;
int specialChar;
int alphabetCount [ALPHABET_SIZE];
while (counter < ALPHABET_SIZE) {
counter = 0;
alphabetCount [counter] = 0;
counter ++;
}
while (inputChar != EOF) {
if (inputChar >= FIRST_LC_LETTER && inputChar <= LAST_LC_LETTER) {
alphabetCount [inputChar - FIRST_LC_LETTER] ++;
} else if (inputChar>=FIRST_UC_LETTER && inputChar<=LAST_UC_LETTER) {
alphabetCount [inputChar - FIRST_UC_LETTER] ++;
} else if (inputChar >= 0 && inputChar <= 9) {
numbers = 0;
numbers ++;
} else if (inputChar == ' ') {
spaces = 0;
spaces ++;
} else {
specialChar = 0;
specialChar ++;
}
}
printf ("Numbers: %d\nSpaces: %d\n Special characters: %d\n", numbers,
spaces, specialChar);
}
Here is a similar approach to consider. It has been written to remove dependencies from all libc header files except stdio.h. Rather than calling the character classification functions in ctype.h it relies on the ASCII values for each of the characters to set the alphabetCount indexes. Neither approach is better/worse than the other, they just illustrate different ways of approaching the same problem with the various tools available.
#include <stdio.h>
#define ALPHABET_SIZE 26
void freqAnalysis (FILE *fp, int *cnt);
int main (void)
{
int position = 0;
char *alphabet = "abcdefghijklmnopqrstuvwxyz";
int alphabetCount[ALPHABET_SIZE] = {0};
printf ("\nThe frequency analysis of the input characters:\n\n");
freqAnalysis (stdin, alphabetCount);
for (position = 0; position < ALPHABET_SIZE; position++)
printf (" %c/%c : %d\n", alphabet[position] - 32,
alphabet[position], alphabetCount[position]);
return 0;
}
void freqAnalysis (FILE *fp, int *cnt)
{
int c, numbers, spaces, specialChar;
c = numbers = spaces = specialChar = 0;
while ((c = fgetc (fp)) != '\n' && c != EOF)
{
if (c >= 'A' && c <= 'Z')
cnt[c - 'A']++;
else if (c >= 'a' && c <= 'z')
cnt[c - 'a']++;
else if (c >= '0' && c <= '9')
numbers++;
else if ( c == ' ' )
spaces++;
else
specialChar++;
}
printf (" Numbers : %d\n Spaces : %d\n Special : %d\n\n", numbers, spaces, specialChar);
}
Output
$ ./bin/charcount <<<"The Quick Brown Fox Jumps Over 1001 Lazy Dogs."
The frequency analysis of the input characters:
Numbers : 4
Spaces : 8
Special : 1
A/a : 1
B/b : 1
C/c : 1
D/d : 1
E/e : 2
F/f : 1
G/g : 1
H/h : 1
I/i : 1
J/j : 1
K/k : 1
L/l : 1
M/m : 1
N/n : 1
O/o : 4
P/p : 1
Q/q : 1
R/r : 2
S/s : 2
T/t : 1
U/u : 2
V/v : 1
W/w : 1
X/x : 1
Y/y : 1
Z/z : 1
policy of modified to be processed by passing a file handle and an secured array in main.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define ALPHABET_SIZE 26
#define FIRST_LC_LETTER 'a'
#define FIRST_UC_LETTER 'A'
void freqAnalysis(FILE *fin, int counter[]);
int main (int argc, char *argv[]) {
int position;
char alphabet[ALPHABET_SIZE] = {'a','b','c','d','e','f','g','h','i','j',
'k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};//unused
int alphabetCount[ALPHABET_SIZE] = {0};
freqAnalysis(stdin, alphabetCount);
for (position = 0; position < ALPHABET_SIZE; position++){
printf ("Letter %c: %d\n", alphabet[position], alphabetCount[position]);
}
return EXIT_SUCCESS;
}
void freqAnalysis(FILE *fp, int alphabetCount[]) {
int inputChar;
int numbers , spaces, specialChar;
numbers = spaces = specialChar = 0;
while((inputChar=fgetc(fp)) != EOF) {
if(islower(inputChar)){
alphabetCount[inputChar - FIRST_LC_LETTER]++;
} else if(isupper(inputChar)) {
alphabetCount[inputChar - FIRST_UC_LETTER]++;//this relies on order of character codes.
} else if(isdigit(inputChar)) {
numbers++;
} else if(inputChar == ' ') {//isspace(inputChar)
spaces++;
} else {
specialChar ++;
}
}
printf("Numbers: %d\nSpaces: %d\nSpecial characters: %d\n", numbers,
spaces, specialChar);
}

Program not registering my input correctly

#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
//function prototypes
void checkAnswer(char *, char[]);
int main(void) {
char *strGame[5] = { "ADELANGUAGEFERVZOPIBMOU", "ZBPOINTERSKLMLOOPMNOCOT",
"PODSTRINGGDIWHIEEICERLS", "YVCPROGRAMMERWQKNULTHMD",
"UKUNIXFIMWXIZEQZINPUTEX" };
char answer[80] = { 0 };
int displayed = 0;
int x;
int startTime = 0;
system("clear");
printf("\n\n\tWord Find\n\n");
startTime = time(NULL);
for (x = 0; x < 5; x++) {
/* DISPLAY TEXT FOR A FEW SECONDS */
while (startTime + 3 > time(NULL)) {
if (displayed == 0) {
printf("\nFind a word in: \n\n");
printf("%s\n\n", strGame[x]);
displayed = 1;
}
}
system("clear");
printf("\nEnter word found: ");
fgets(answer, 80, stdin);
checkAnswer(strGame[x], answer);
displayed = 0;
startTime = time(NULL);
}
}
void checkAnswer(char *string1, char string2[]) {
int x;
for (x = 0; x <= strlen(string2); x++)
string2[x] = toupper(string2[x]);
if (strstr(string1, string2) != 0)
printf("\nGreat job!\n");
else
printf("\nSorry, word not found!\n");
}
When I run the code, it doesn't register my input correctly. It tells me that the word wasn't found. I used toupper to make my input the same as my strings and strstr to compare my input with the strings. I took this from a basic C programming book. It used gets. I know that you shouldn't use gets so I changed it to fgets. Is this where the problem is? Any suggestions?
You can avoid the issue with the \n (newline) mentioned by BLUEPIXY -- namely, that gets() removes it but fgets() does not -- by reversing the terms in your call to checkAnswer():
checkAnswer(answer, strGame[x]);
checkAnswer() then uses the same order with strstr(). If you search for "foobar" in "foobar\n", strstr() will return a pointer. But if you search for "foobar\n" in "foobar", it won't.
The newline is there because the user hits Enter. So another way around this would be to add a \n to the end of all your strGame[] strings. Or, you could remove any newline in the answer with:
void truncateAtNewline (char *str) {
char *p = strchr(str, '\n');
if (p) *p = '\0';
}
The problem is that fgets() will leave the newline at the end of the string. When you type the word, then you press Enter and fgets() interprets that as input.
So, a way to bypass this is to eat the newline by doing this:
fgets(answer, 80, stdin);
// go to the last position where the
// newline is placed and replace it
// with the null terminator
answer[strlen(answer)-1] = '\0';
Also here:
for (x = 0; x <= strlen(string2); x++)
string2[x] = toupper(string2[x]);
the <= is not needed, since you start from 0, thus change it to this:
for (x = 0; x < strlen(string2); x++)
string2[x] = toupper(string2[x]);
How I found your problem? I used printf to output the strings before comparing them.
void checkAnswer(char *string1, char string2[]) {
int x;
for (x = 0; x < strlen(string2); x++)
string2[x] = toupper(string2[x]);
printf("|%s|\n", string1);
printf("|%s|\n", string2);
if (strstr(string1, string2) != 0)
printf("\nGreat job!\n");
else
printf("\nSorry, word not found!\n");
}
Output before my fix:
|ADELANGUAGEFERVZOPIBMOU|
|ADEL
|
Output after the fix:
|ADELANGUAGEFERVZOPIBMOU|
|ADEL|
Or you can use a function to trim newlines and spaces. I have some methods here.
Consider also not using system().
Moreover, always add a return 0; line of code before your main() ends.

Resources