I'm making a program that takes the characters from congress.txt makes them all uppercase, then "shifts them two characters", (A goes to C) (Z goes to B). But nothing is being printed, my main concern is if my arrays are being stored and passed to the different functions properly.
This is what is in congress.txt:
Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the government for a redress of grievances.
#include<stdio.h>
int processFile(int *store);
int cipher(int *store, int *code);
int outputCode(int *code);
int main(void){
int store[300], code[300], i;
processFile(store);
cipher(store, code);
outputCode(code);
getchar();
return 0;
}
void processFile(int *store){
int i, a = 0;
FILE *f = fopen("congress.txt", "r");
for (i = 0; a != EOF;){
fscanf(f, "%c", &a); //store character in a
if (a <= 'Z' && a >= 'A'){ //store uppercase letters
store[i] = a;
i++;
}
if (a <= 'z' && a >= 'a'){ //store lowercase letters as uppercase
store[i] = a - 32;
i++;
}
}
i++;
store[i] = '\0';
}
void cipher(int *store, int *code){
int i;
for (i = 0; store[i] != 0; ++i){
if (store[i] <= 'X' && store[i] >= 'A'){ //tests to see if the letter is between A and X
code[i] = (char)(store[i] + 2); //shifts letter by two characters
}
if (store[i] >= 'Y' && store[i] <= 'Z'){
code[i] = (char)(store[i] - 24); //shifts Y and Z to A or B respectively
}
}
}
void outputCode(int *code){
int i, a, b;
for (a = 0; code[a] != 0; ++a){
if (!(a % 50)){ //makes a newline every 50 characters
printf("\n");
}
for (b = 0; code[a] != 0 && b <= 5; ++b){ //prints chunks of 5 characters then makes a space
printf("%c", code[a]);
}
printf(" ");
}
}
There are several things wrong with your code - many of which your compiler will complain about.
To start - you don't have return values for functions that are declared int. Just make them void, or return something.
Second - you declare int a; but proceed to use it like a char. Declare it how you use it.
Third - testing for end of file is done with feof(f) not a != EOF.
Fourth - when you output your code you need to increment a, otherwise you get the same value five times:
VVVVVV JJJJJJ KKKKKK UUUUUU KKKKKK UUUUUU UUUUUU
etc.
Fifth - your printing routine doesn't guarantee it will stop - if you have a single '\0' followed by other garbage, you will print more garbage (unless it happens on a multiple of 5). You need to pad your cipher with zeros.
So - working code:
#include<stdio.h>
int processFile(int *store);
int cipher(int *store, int *code);
int outputCode(int *code);
int main(void){
int store[300], code[300], i;
processFile(store);
cipher(store, code);
outputCode(code);
printf("\n=====\n\n");
return 0;
}
int processFile(int *store){
int i;
char a = 0;
FILE *f = fopen("congress.txt", "r");
for (i = 0; !feof(f) && i<299;){
fscanf(f, "%c", &a); //store character in a
if (a <= 'Z' && a >= 'A'){ //store uppercase letters
store[i] = a;
i++;
}
if (a <= 'z' && a >= 'a'){ //store lowercase letters as uppercase
store[i] = a - 32;
i++;
}
}
store[i]='\0';
return 0;
}
int cipher(int *store, int *code){
int i;
for (i = 0; store[i] != 0; ++i){
if (store[i] <= 'X' && store[i] >= 'A'){ //tests to see if the letter is between A and X
code[i] = (char)(store[i] + 2); //shifts letter by two characters
}
if (store[i] >= 'Y' && store[i] <= 'Z'){
code[i] = (char)(store[i] - 24); //shifts Y and Z to A or B respectively
}
}
for(; i<300; i++) code[i]=0; // pad with zeros
return 0;
}
int outputCode(int *code){
int i, a, b;
for (a = 0; code[a] != 0; ++a){
if (!(a % 50)){ //makes a newline every 50 characters
printf("\n");
}
for (b = 0; code[a] != 0 && b <= 5; ++b){ //prints chunks of 5 characters then makes a space
printf("%c", code[a++]);
}
printf(" ");
}
return 0;
}
Related
I am new to C and I am trying to scan two char variables in one line.
I used #define _CRT_SECURE_NO_WARNINGS because I have to.
This is the piece of code that annoys me: scanf_s("%c-%c", &x,1, &y,1);
When inputting 2 chars, it looks something like this ---> e-f or a-b
Also, I need to lose scanf_s and make it into scanf only.
Another thing that is kinda weird to me is that after I input two chars and do actions later, I reset values of x and y to 0 and need to input them again. However, when I type them in, I get completely different values.
Here is the whole code that I wrote so far. Task: input 2 letters and print them in order specified in input e.g. a-c --> ABC or c-a --> cba
#include<stdio.h>
#define MAX 100
int main(){
char niz[MAX];
char kraj[MAX] = {0};
int razlika;//difference
char x, y;
int i;
char trenutniznak; //current character
int stoppolje=0;//stop field
int temp = 0;
while (1)
{
scanf_s("%c-%c", &x,1, &y,1);
if (x == '.' || y == '.')
{
return 0;
}
else if (y > x)//od pocetka do kraja
{ //(from start to end )
razlika = y - x + 1;
for (i = stoppolje+1, trenutniznak=x; i <= razlika; i++, trenutniznak++)
{
niz[i] = trenutniznak;
temp = i;
}
stoppolje = temp; // polje na kojem je zadnji znak
//(the field where the last character is )
x = 0;
y = 0;
razlika = 0;
}
else
{
printf("\n");
return 0;
}
}
}
Try to understand and then implement in your code
char c;
scanf(" %c",&c); // a whitespace character in scanf() would ignore any number of whitespace characters left in the input stream
printf("%c",c);
you can go through %c conversion specifier
Scanning 2 chars in one line
Simplify. Use fgets() to read a line of user input and convert that into a string.
Avoid scanf(). It does not well read a line and is difficult to use when input is unexpected.
char buf[80];
if (fgets(buf, sizeof buf, stdin)) {
Now scan/parse the string into the two characters. Look for bad input.
char extra;
if (sscanf(buf, "%c-%c %c", &x, &y, &extra) != 2) {
fprintf(stderr, "invalid input <%s>\n", buf);
} else {
// Use x, y in some fashion
printf("Good input <%c> <%c>\n", x, y);
}
}
Sneak: If you must use scanf(), add a scanf(""); before the fgets() to use scanf(). It will not read anything.
"Task: input 2 letters and print them in order specified in input e.g. a-c --> ABC or c-a --> cba"
If scanf() is not necessary, consider using fgets(), then the resulting string array, say char buf[4] = {0}; the the array elements buf[0], buf[1] and buf[2] will contain for example 'a', '-' and 'c'. (buf[3] will contain \0 character.) These are just numeric values that happen to be within the ASCII character range, but can also be logically manipulated as numbers, so just output the sequence of numbers using a format specifier that will guarantee they appear as ASCII:
int main(void)
{
char buf[4] = {0};
int c = 0;
printf("Enter maximum of three characters: eg 'a-d'\n(or ctrl-c to exit.)\n");
while(fgets(buf, sizeof buf, stdin))
{
//test input
if((buf[0] < 'a') || (buf[0] > 'Z') ||
(buf[2] < 'a') || (buf[2] > 'Z') ||
(buf[1] != '-')
)
{
printf("Invalid input. Try again\n(or hit ctrl-c to exit.");
}
else
{
buf[strcspn(buf, "\n")] = 0;//remove newline
if(buf[0] > buf[2])
{
for(char i = buf[0];i >= buf[2];i--)
{
printf("%c", i);
}
printf("\n");
}
else if ((buf[0] < buf[2]))
{
for(char i = buf[0];i<= buf[2];i++)
{
printf("%c", toupper(i));//note UPPER CASE as specified
}
printf("\n");
}
memset(buf, 0, sizeof buf);//reset buffer for next iteration.
while((c = getchar()) != '\n' && c != EOF);//clear \n from stdin
printf("\nEnter maximum of three characters: eg 'a-d'\n(or ctrl-c to exit.)\n");
}
}
}
Well I managed somehow to do it, thank you everyone for answering my question :)
#include<stdio.h>
#define MAX 1000
int main()
{
char niz[MAX];
char kraj[MAX] = {0};
int razlika;
char x, y;
int i;
char trenutniznak;
int stoppolje=-1;
int temp = 0;
while (1)
{
scanf_s(" %c-%c", &x,1, &y,1);
if (x == '.' || y == '.')
{
for (i = 0; i <= stoppolje; i++)
{
printf("%c", niz[i]);
}
return 0;
}
else if(x == '_' || y == '_')
{
niz[stoppolje + 1] = ' ';
stoppolje += 1;
}
else if (y > x)//od pocetka do kraja
{
razlika = y - x + 1;
trenutniznak = x;
for (i = stoppolje+1, trenutniznak; i < razlika+stoppolje+1; i++, trenutniznak++)
{
niz[i] = trenutniznak;
temp = i;
}
stoppolje = temp; // polje na kojem je zadnji znak
x = 0;
y = 0;
razlika = 0;
}//ako idemo po redosljedu abecednom
else if(x>y)
{
razlika = x-y + 1;
trenutniznak = x;
for (i = stoppolje+1, trenutniznak; i < razlika + stoppolje + 1; i++, trenutniznak--)
{
niz[i] = trenutniznak;
temp = i;
}
stoppolje = temp;
x = 0;
y = 0;
razlika = 0;
}
else if (x == y)
{
razlika = 0;
trenutniznak = x;
for (i = stoppolje + 1, trenutniznak; i < razlika + stoppolje + 2; i++, trenutniznak++)
{
niz[i] = trenutniznak;
temp = i;
}
stoppolje = temp;
x = 0;
y = 0;
razlika = 0;
}
}
}
It's supposed to do the following
Ask for input : Stack (e.g)
Ask for key : qwertyuioplkjhgfdsazxcvbnm (e.g)
Convert into cipher text : Azqel
Here's the new updated code:
//Encrypting user input by using 26 character long alphabetic key provided by user
#include <stdio.h>
#include <string.h>
int main(){
char key[26];
char text[1000];
//Prompt user for key
do{
printf("Provide a 26 character long key : ");
scanf("%s", key);
//If key is empty, exit code
if(strlen(key) == 0){
printf("Error: Empty input");
return 1;
}
//If key is incomplete, prompt user again for complete key
if(strlen(key)!= 26){
printf("Error: Incomplete key\n");
}
}while(strlen(key) != 26);
//If key has values other than alphabets, exit code
for(int i= 0, n= strlen(key); i<n; i++){
if((key[i]< 'a' || key[i]> 'z') && (key[i]< 'A' || key[i]> 'Z')){
printf("Error: Invalid key");
return 2;
}
}
//If key has repeated values, exit code
for(int i= 0; i< strlen(key); i++){
for(int j= i+ 1; key[j]!= '\0'; j++){
int x, y;
if(islower(key[i])){
x = key[i] - 'a';
}
else {
x = key[i] - 'A';
}
if(islower(key[j])){
y = key[j] - 'a';
}
else {
y = key[j] - 'A';
}
if(x == y){
printf("Error: Repeated characters in key");
return 3;
}
}
}
//Prompt user for input
printf("Plaintext : ");
scanf("%s", text);
//If input is empty, exit code
if(strlen(text) == 0){
printf("Error: Empty input");
return 4;
}
printf("Ciphertext: ");
for(int i= 0, n= strlen(text); i< n; i++){
//Encrypting small letters
if(text[i] >= 'a' && text[i] <= 'z'){
printf("%c", key[text[i]-'a']);
}
//Encrypting capital letters
else if(text[i] >= 'A' && text[i] <= 'Z'){
printf("%c", key[text[i]-'A']-('a'-'A'));
}
//Printing characters other than alphabets
else{
printf("%c", text[i]);
}
}
return 0;
}
The bug where code was treating lower case characters and upper case characters differently even if they were same has been fixed now.
If the key is for example : qwertyuioplkjhgfdsazxcvbmM (it has the letters 'm' and 'M' but they were being treated as different characters)
you can try this:
#include <stdio.h>
#include <string.h>
int main(){
char s[1000];
char t[26];
printf("Text: ");
scanf("%s", s);
printf("Key: ");
scanf("%s", t);
for(int i= 0, n= strlen(s); i< n; i++){
if(s[i] >= 'a' && s[i] <= 'z') printf("%c", t[s[i]-'a']);
else printf("%c", t[s[i]-'A'] + ('A'-'a'));
}
return 0;
}
and as said in the comments, try not to use numbers like 97 and 122, use 'a' and 'z' instead.
and for the bug mentioned in the updated code, instead of a simple check like key[j] == key[i] do this
int x, y;
if(islower(key[i])) x = key[i] - 'a';
else x = key[i] - 'A';
if(islower(key[j])) y = key[j] - 'a';
else y = key[j] - 'A';
if(x == y){
printf("Error: Repeated characters in key");
return 3;
}
or you can use a bool check[26], traverse the key, make the value of a character true if(islower(key[i])) check[key[i]-'a'] = true; else check[key[i]-'A'] = true; and lastly check whether the entire bool array is true.
I want to count letters,numbers,symbols using function password Seems like it doesn't count out numbers correctly because i get 0 for every printf in the end
#include <stdio.h>
void password(char * str[],int together,int numbers,int symbols,int i,int uppercase,int lowercase);
int main()
{
char str[100];
int together, numbers, symbols, i,uppercase,lowercase;
together = numbers = symbols = i = uppercase = lowercase = 0;
printf("password : ");
gets(&str);
printf(" %s", str);
password(&str,together,numbers,symbols,i,uppercase,lowercase);
printf("Number of letters = %d\n", together);
printf("number uppercase = %d\n", uppercase);
printf("Number lowecase = %d\n", lowercase);
printf("numbers = %d\n", numbers);
printf("Simboli = %d", symbols);
if (together >= 8 && numbers >= 2){
printf("\nPassword is correct");
}else{
printf("\nPassword isn't correct");
}
return 0;
}
void password(char * str[],int together,int numbers,int symbols,int i,int uppercase,int lowercase){
while(*str[i]!='\0')
{
if((*str[i]>='a' && *str[i]<='z') || (*str[i]>='A' && *str[i]<='Z'))
{
together++;
}
else if(*str[i]>='0' && *str[i]<='9')
{
numbers++;
}
else if(*str[i] >= 'A' && *str[i] <= 'Z') {
uppercase++;
}
else if(*str[i] >= 'a' && *str[i] <= 'z'){
lowercase++;
}
else
{
symbols++;
}
i++;
}
}
I get zeroes for every number,letter & symbol program runs without any error I tried changing some stuff but I am currently learning C so it is hard for me!
Few points : 1) There is no need to pass i as argument since you can get the length of your string with strlen from string.h (which returns a size_t type and not an int). 2) You passed your arguments as value, which means that they'll only change locally to your function. 3) Don't use the gets function that is not safe, you may want to use fgets or scanf.
#include <string.h>
#include <stdio.h>
void password(char *str, int *together, int *numbers, int *symbols, int *uppercase, int *lowercase){
for(size_t i=0; i<strlen(str); i++){
if(str[i] >= '0' && str[i] <= '9') (*numbers)++;
if(str[i] >= 'A' && str[i] <= 'Z') (*uppercase)++;
if(str[i] >= 'a' && str[i] <= 'z') (*lowercase)++;
if(str[i] >= '!' && str[i] <= '/') (*symbols)++;
}
*together = (*uppercase) + (*lowercase);
}
int main(void){
char str[100] = "Pa$$w0/2d";
int together = 0;
int numbers = 0;
int symbols = 0;
int uppercase = 0;
int lowercase = 0;
password(str, &together, &numbers, &symbols, &uppercase, &lowercase);
printf("Letters = %d\n", together);
printf("Uppercase = %d\n", uppercase);
printf("Lowercase = %d\n", lowercase);
printf("Numbers = %d\n", numbers);
printf("Symbols = %d\n", symbols)
return 0;
}
I tried to write a program that prints a diamond with mirrored letters like the following shape:
a
aba
abcba
abcdcba
abcdedcba
abcdefedcba
abcdedcba
abcdcba
abcba
aba
a
here is what I have done already:
#include <stdio.h>
int main()
{
int n, c, k,f=0, space = 1;
char ch='a';
printf("enter the size of diamond\n");
scanf("%d", &n);
space = n - 1;
for (k = 1; k <= n; k++)
{
for (c = 1; c <= space; c++)
printf(" ");
space--;
for (c = 1; c <= 2*k-1; c++)
if (c <= f)
printf("%c", ch);
ch++;
if (c>f)
ch--;
printf("%c", ch);
printf("\n");
}
space = 1;
for (k = 1; k <= n - 1; k++)
{
for (c = 1; c <= space; c++)
printf(" ");
space++;
for (c = 1 ; c <= 2*(n-k)-1; c++)
printf("a");
printf("\n");
}
return 0;
}
But apparently there is some error in this code, can any one help me detect it?
If you replace this
for (c = 1 ; c <= 2*(n-k)-1; c++)
printf("a");
with this
for (c = 0 ; c < 2*(n-k)-1; c++) // note the different conditions
printf("%c", 'a' + c); // print char instead of string
you should get each line of the correct length but with increasing chars like
abcde
but it doesn't decrease from the midpoint. I leave that to you!
It would be easier to separate tasks to function. So the function to calculate the character to be printed based on the position and the line length would be:
int getCharAtPos(int pos, int len)
{
if (pos > len / 2)
{
return 'a' + len - pos;
}
else
{
return 'a' + pos - 1;
}
}
And then instead of printf("a") you would use
for (c = 1; c <= 2*k-1; c++)
printf("%c", getCharAtPos(c, 2*k-1));
.....
for (c = 1 ; c <= 2*(n-k)-1; c++)
printf("%c", getCharAtPos(c, 2*(n-k)-1));
There is a second solution of the problem.
You can use recursion.
I wrote an example for your task.
//--------------
// Recursive Out one Simbol
void DamSimRec(char chOut ,int scnt)
{
printf("%c", chOut);
if (scnt > 1)
{
DamSimRec(chOut + 1, scnt - 1);
printf("%c", chOut);
}
}// Print Space
//--------------
void SpaceOut(int pSizeSpace)
{
int a_c;
for (a_c = 0; a_c < pSizeSpace; a_c++)
printf(" ");
}
//--------------
// Recursive Print One String Krylov E.A.
void DamRec(int space, int sout)
{
SpaceOut(space);//space;
DamSimRec('a', sout);//Simbols
printf("\n");
if (space > 0)
DamRec(space-1, sout+1);
if (sout > 1)
SpaceOut(space + 1);
DamSimRec('a', sout - 1);
}
printf("\n");
}
main()
{
int aSize;
printf("enter the size of diamond\n");
scanf_s("%d", &aSize);
DamRec(aSize , 1);
}
...So, You can use that, but remember about stack.
int n, c, k, space;
printf("enter the size of diamond\n");
scanf("%d", &n);
char s[n+2];
s[0] = 'a';s[1] = '\0';
for(c = 0; c < n; ++c){
space = n - c -1;
printf("%*s", space, "");
k = printf("%s", s) - 1;
while(--k >=0)
putchar(s[k]);
puts("");
s[c+1] = s[c] + 1;
s[c+2] = '\0';
}
for(c = 1; c < n; ++c){
space = c;
printf("%*s", space, "");
k = printf("%.*s", n - c, s) - 1;
while(--k >=0)
putchar(s[k]);
puts("");
}
#include <stdio.h>
void print(char from, char to){
putchar(from);
if(from < to){
print(from+1, to);
putchar(from);
}
}
int main(void){
int c = 0, n, k = 1;
printf("enter the size of diamond\n");
scanf("%d", &n);
do{
printf("%*s", n - c -1, "");
print('a', 'a' + c);
puts("");
if(c + 1 == n)
k = -k;
c += k;
}while(c>=0);
return 0;
}
I have seen other solutions to this problem where a pointer is used. I don't understand the workings of a pointer enough to implement them into this program. If the solution requires one, would someone please be able to explain why? I have been trying various things with this program all night and gotten nowhere. I read the relevant text in 'The C Programming Language' book, where the exercise is from. I can't be the only person stumped by this D:
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#define MAX 1000
int htoi(char s[]);
main()
{
char line[MAX];
int i, c;
printf("Enter the strig to convert to an integer:");
for(i=0; i<MAX && (c=getchar())!=EOF && c != '\n'; ++i)
line[i] = c;
int a =0;
a = htoi(line);
printf("%d", a);
}
int htoi(char s[])
{
int i, n, z;
n=0;
int total = 0;
for(i=0; s[i] != '\0'; ++i)
{
if (s[i] == 'a'||s[i] == 'A')
n = 10;
else if(s[i] == 'b'||s[i] == 'B')
n = 11;
else if(s[i] == 'c'||s[i] == 'C')
n = 12;
else if(s[i] == 'd'||s[i] == 'D')
n = 13;
else if(s[i] == 'e'||s[i] == 'E')
n = 14;
else if(s[i] == 'f'||s[i] == 'F')
n = 15;
else
n = s[i];
z = n * pow(16, i);
total = total + z;
}
return total;
}
Someone correct me if I am wrong. But you're not putting a null terminator in your char array:
for(i=0; i<MAX && (c=getchar())!=EOF && c != '\n'; ++i)
line[i] = c;
Later on, you do
for(i=0; s[i] != '\0'; ++i)
But since you never appended a null terminator the above for loop will iterate PAST the bounds of the array until it sees a null somewhere on the stack or it segfaults.
you should be doing the following:
for(i=0; i<(MAX-1) && (c=getchar())!=EOF && c != '\n'; ++i)
line[i] = c;
line[i+1] = '\0';
Note the (MAX-1)
P.S Don't run anything that doesn't require root as root, see: least privilege principle
Your problem is here:
else
n = s[i]; // <- n is getting the character code value of S[i]
To solve, I suggest to do:
else
n = s[i] - '0';
EDITED:
You have two problems else:
You need to null terminate the line char (your string hasn't '\0')
You are inverting the power math (digit more at left are more significants than at right position)
To solve (1), do that:
for(i=0; i<MAX && (c=getchar())!=EOF && c != '\n'; ++i)
line[i] = c;
line[i] = '\0'; // <-- added here
To solve (2), do that:
int total = 0;
int len = strlen(s) - 1; // <- added here
...
z = n * pow(16, len - i); // <- change here
Another way, you can avoid using the expensive pow function by just shifting 4 bits to left as in code bellow:
instead of:
z = n * pow(16, i);
total = total + z;
do:
total <<= 4; // changed here
total += n; // and here