My program below conducts a Caesar's cipher in C. For some reason, after a message has been input by the user, the printf(" \nEnter key:") and
scanf("%d", &key) statements get "jumped" over. My thought was something related to the input buffer having a char and newline entered causing the jump (hence the fflush attempt). How do I prevent this behavior?
#include <stdio.h>
#include <stdlib.h>
int main() {
char message[50], ms;
int i, key, choice;
printf("Enter 1. to Encrypt, or 2. to Decrypt: ");
scanf(" %d", &choice);
printf("Enter a message to process: ");
scanf(" %c", message);
printf(" \nEnter key:");
fflush(stdin);
scanf("%d", &key);
for (i = 0; message[i] != '\0'; ++i) {
ms = message[i];
if (ms >= 'a' && ms <= 'z' && choice == 1) {
ms = ms + key;
if (ms >= 'a' && ms <= 'z' && choice == 2) {
ms = ms - key;
if (ms > 'z') {
ms = ms - 'z' + 'a' - 1;
}
}
message[i] = ms;
} else
if (ms >= 'A' && ms <= 'Z' && choice == 1) {
ms = ms + key;
if (ms >= 'A' && ms <= 'Z' && choice == 2) {
ms = ms - key;
}
if (ms > 'Z') {
ms = ms - 'Z' + 'A' - 1;
}
message[i] = ms;
}
if (choice == 1) {
printf(" \nEncrypted message: %s", message);}
else if (choice == 2) {
printf(" \nDecrypted message: %s", message);}
}
}
#ddisec I have noted 3 mistakes in your code .
First your scanf(" %c", message); .Here you have to use %s (String).
Second the result printing statements should be outside for-loop.
Third putting if(ms >= 'a' && ms <= 'z'&& choice == 2) inside if (ms >= 'a' && ms <= 'z' && choice == 1) dose not make any sense.
Try this corrected code:-
#include <stdio.h>
#include <stdlib.h>
int main()
{
char message[50], ms;
int i, key, choice;
printf("Enter 1. to Encrypt, or 2. to Decrypt: ");
scanf("%d", &choice);
getchar(); // to handle unwanted newline.
printf("Enter a message to process: ");
scanf("%49[^\n]", message);
printf(" \nEnter key:");
scanf("%d", &key);
for (i = 0; message[i] != '\0'; ++i)
{
ms = message[i];
if (ms >= 'a' && ms <= 'z' && choice == 1)
{
ms = ms + key;
}
else if (ms >= 'a' && ms <= 'z' && choice == 2)
{
ms = ms - key;
}
else if (ms > 'z')
{
ms = ms - 'z' + 'a' - 1;
}
else if (ms >= 'A' && ms <= 'Z' && choice == 1)
{
ms = ms + key;
}
else if (ms >= 'A' && ms <= 'Z' && choice == 2)
{
ms = ms - key;
}
else if (ms > 'Z')
{
ms = ms - 'Z' + 'A' - 1;
}
message[i] = ms; // Only single modification code needed.
}
if (choice == 1)
{
printf(" \nEncrypted message: %s", message);
}
else if (choice == 2)
{
printf(" \nDecrypted message: %s", message);
}
}
There are multple problems in your code:
The way you enter the message is incorrect: scanf(" %c", message); reads a single byte into the message first element and does not even make it a C string. Use this instead, to read the message with embedded spaces:
scanf("%49[^\n]", message);
There are logic bugs in the rest of the code: for example, you test for choice == 2 inside the block that is only executed if choice == 1...
Here is a simplified version:
#include <stdio.h>
int main() {
char message[50];
int i, key, choice;
printf("Enter 1. to Encrypt, or 2. to Decrypt: ");
if (scanf("%d", &choice) != 1)
return 1;
printf("\nEnter a message to process: ");
if (scanf("%49[^\n]", message) != 1)
return 1;
printf("\nEnter key:");
if (scanf("%d", &key) != 1)
return 1;
for (i = 0; message[i] != '\0'; ++i) {
int ms = message[i];
if (ms >= 'a' && ms <= 'z') {
if (choice == 1)
ms = 'a' + ((ms - 'a') + key) % 26;
if (choice == 2)
ms = 'a' + ((ms - 'a') + 26 - key) % 26;
message[i] = ms;
} else
if (ms >= 'A' && ms <= 'Z') {
if (choice == 1)
ms = 'A' + ((ms - 'A') + key) % 26;
if (choice == 2)
ms = 'A' + ((ms - 'A') + 26 - key) % 26;
message[i] = ms;
}
}
if (choice == 1)
printf("\nEncrypted message: %s\n", message);
if (choice == 2)
printf("\nDecrypted message: %s\n", message);
}
return 0;
}
Related
This question already has answers here:
What is the behavior of integer division?
(6 answers)
Closed 1 year ago.
I'm doing homework and I have no idea why the %lf selector isn't working. I have to take a line of characters and determine if they can be a floating point or whole number and then print that number. Here's the code:
#include <stdio.h>
int main() {
char ch;
int isNumber = 1, dot = 0, negativeMult = 10;
double result = 0;
printf("\nEnter characters: ");
scanf("%c", &ch);
while (ch != 10) {
if ((ch >= '0' && ch <= '9')) {
if (dot) {
result = result + (ch - '0') / negativeMult;
negativeMult *= 10;
} else {
result = result * 10 + (ch - '0');
}
} else
if (ch == '.')
if (dot)
isNumber = 0;
else
dot = 1;
else {
isNumber = 0;
break;
}
scanf("%c", &ch);
}
if (isNumber)
printf("\nThe number is %lf", result);
else
printf("\nEntered characters are not able to be a number.");
return 0;
}
Edit: I forgot output. Sorry.
Input: Enter characters: 123.648
Output: The number is 123.000000
the error is here:
result = result + (ch - '0') / negativeMult;
(ch - '0') / negativeMult is integer division and it is always 0
it has to be
result = result + (double)(ch - '0') / negativeMult;
some more small errors amendments:
int main(void)
{
char ch;
int isNumber = 1, dot = 0, negativeMult = 10;
double result = 0;
int scanfresult;
printf("\nEnter characters: ");
scanfresult = scanf("%c", &ch);
while (ch != '\n' && scanfresult == 1)
{
if ((ch >= '0' && ch <= '9'))
{
if (dot)
{
result = result + (double)(ch - '0') / negativeMult;
negativeMult *= 10;
}
else
{
result = result * 10 + (ch - '0');
}
}
else if (ch == '.')
if (dot)
isNumber = 0;
else
dot = 1;
else
{
isNumber = 0;
break;
}
scanfresult = scanf("%c", &ch);
}
if (isNumber)
printf("\nThe number is %f", result);
else
printf("\nEntered characters are not able to be a number.");
return 0;
}
https://godbolt.org/z/nTKdjYsz8
I'm doing an exercise where i ask the user for an input and then i cypher de input.
Bellow the code:
int main(int argc, char** argv) {
char string[50], cypher[50];
int num, i;
do {
printf("Enter text to cypher: \n");
scanf(" %s", string);
do {
printf("Enter cypher number: ");
scanf(" %d", &num);
while (num > 25) // only 25 letters, get number between >25
{
num -= 25;
}
} while (num <= 0);
for (i = 0; string[i] != '\0'; i++) {
cypher[i] = string[i] + num;
if (cypher[i] > 90 && cypher[i] < 97) // upper case
{
cypher[i] = cypher[i] - 'Z' + 'A' - 1;
}
if (cypher[i] > 122) //lower case
{
cypher[i] = cypher[i] - 'z' + 'a' - 1;
}
}
cypher[i] = '\0';
printf("%s\n", cypher);
}
while (string[0] != '0');
}
I want to exit the do while loop if the user input is '0' when asked to "Enter text to cypher: " without showing the next menssage "Enter cypher number".
Thank you in advance for your help.
after first scanf you should write something like if(string[0] == '0') break;
I made a program that reads a list of grades from a file and calculates the GPA. I have no idea how to properly modularize a program like this, because both the the calculating and the file reading happen simultaneously.
Here is text file contents:
Ariel Lewis
Biology A 4.0
Statistics C 4.0
History A 3.0
Tennis A 1.0
English B 3.0
Here is my code:
#pragma warning (disable:4996)
#include <stdio.h>
#define MAX_LINE 20
#define ERROR -1
float GPA(int, int);
int CoursePoints(int, int);
int GradeToPoints(char);
int main()
{
FILE * fpCredits;
char singleLine[MAX_LINE];
char gradeLetter = '_';
int totalPoints = 0;
int totalCredits = 0;
int credits = 0;
int gradePoint = 0;
int i = 0;
/*
fpCredits = fopen("grades.txt", "w");
fprintf(fpCredits, "Ariel Lewis\n");
fprintf(fpCredits, "Biology A 4.0\n");
fprintf(fpCredits, "Statistics C 4.0\n");
fprintf(fpCredits, "History A 3.0\n");
fprintf(fpCredits, "Tennis A 1.0\n");
fprintf(fpCredits, "English B 3.0\n");
rewind(fpCredits);
*/
fpCredits = fopen("grades.txt", "r");
// DISPLAY INFORMATION
fgets(singleLine, MAX_LINE, fpCredits);
for (i = 0; singleLine[i] != '\n'; i++) {
printf("%c", singleLine[i]);
}
printf("'s Grade Point Average Calculator\n\n");
printf("Course Name Grade Earned Number of Credits Earned\n");
while (!feof(fpCredits)) {
fgets(singleLine, MAX_LINE, fpCredits);
for (i = 0; singleLine[i] != ' '; i++) {
printf("%c", singleLine[i]);
}
printf(" ");
printf("\t");
for (i = 0; singleLine[i] != '\0'; i++) {
if (singleLine[i] == 'A' || singleLine[i] == 'B' || singleLine[i] == 'C' || singleLine[i] == 'D' || singleLine[i] == 'F') {
if (singleLine[i - 1] == ' ' && singleLine[i + 1] == ' ') {
if (singleLine[i + 2] >= '0' && singleLine[i + 2] <= '4') {
credits = singleLine[i + 2] - '0';
}
else {
printf("\n ERROR:FILE_SPACING \n");
break;
}
gradeLetter = singleLine[i];
printf("%c %.1f", gradeLetter, (float)credits);
}
}
}
printf("\n");
}
printf("\n");
rewind(fpCredits);
// CALCULATE INFORMATION
while (!feof(fpCredits)) {
fgets(singleLine, MAX_LINE, fpCredits);
for (i = 0; singleLine[i] != '\0'; i++) {
if (singleLine[i] == 'A' || singleLine[i] == 'B' || singleLine[i] == 'C' || singleLine[i] == 'D' || singleLine[i] == 'F') {
if (singleLine[i - 1] == ' ' && singleLine[i + 1] == ' ') {
if (singleLine[i + 2] >= '0' && singleLine[i + 2] <= '4') {
credits = singleLine[i + 2] - '0';
}
else {
printf("\n ERROR:FILE_SPACING \n");
break;
}
if (singleLine[i] == 'F') {
credits = 0;
}
totalCredits = totalCredits + credits;
gradePoint = GradeToPoints(singleLine[i]);
totalPoints = totalPoints + CoursePoints(gradePoint, credits);
}
}
}
}
rewind(fpCredits);
printf("The GPA for this student is: %.2f and credits earned are: %d.\n\n", GPA(totalPoints, totalCredits), totalCredits);
fclose(fpCredits);
return 0;
}
float GPA(int points, int credits)
{
return (float)points / (float)credits;
}
int CoursePoints(int gradePoints, int credits)
{
return gradePoints * credits;
}
int GradeToPoints(char grade)
{
switch (grade) {
case 'A':
return 4;
case 'B':
return 3;
case 'C':
return 2;
case 'D':
return 1;
case 'F':
return 0;
default:
printf("\n ERROR:DEFAULT \n");
return ERROR;
}
printf("\n ERROR:SKIPPED \n");
return ERROR;
}
First thing to note: modularization is not about simultaneous execution, its ok to read and calculate at the same time, but different modules should perform actual job.
One suggestion how you can make it work is to start with pseudo-code for your algorithm:
total grade = 0;
total grade count = 0;
for every grade in dataset:
print this grade
total grade += this grade;
total grade count++;
print average grade
now, this algorithm does not know anything about files, it works with "dataset", how this can be translated into code, one variant (pseudo c style):
Grade module
Implementation is to put this into grade.h file
struct Grade {
char gradeLetter;
int gradeValue;
int gradeCredits;
}
File based dataset module
Implementation is to put this into FileBaseGradeDataSource.h/c file
FILE* getDataSource() {
///fopen....
}
void closeDataSource(FILE*f) {
///fclose
}
boolean hasMore(FILE*f) {
return !eof(f);
}
Grade getNextGrade(FILE*f) {
// your logic to read and parse string from file
}
Main module
Implementation is to put this into main.c
FILE* datasource = getDataSource();
int totalPoints = 0;
int totalCredits = 0;
while (hasMore(datasource)) {
Grade grade = getNextGrade(datasource);
// printf, save
}
// print average
closeDataSource(datasource);
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <iostream>
#include <cstdlib>
using namespace std;
#include "bcio2.h"
int error, x;
char totalimpulse[80], averageimpulse[80], ejection[50], emptymass[50], enginemass[50], fuelmass[50];
char launch[50];
void validate_number();
int main(void)
{
clrscr();
do{
printf("\nTotal Impulse delivered: ");
gets(totalimpulse);
validate_number();
} while (error != 0);
do{
printf("\nAverage Impulse delivered: ");
gets(averageimpulse);
validate_number();
} while (error != 0);
do{
printf("\nTime that ejection charge fires: ");
gets(ejection);
validate_number();
} while (error != 0);
do{
printf("\nThe mass of the empty vehicle: ");
gets(emptymass);
validate_number();
} while (error != 0);
do{
printf("\nThe mass of the engine: ");
gets(enginemass);
validate_number();
} while (error != 0);
do{
printf("\nThe mass of fuel: ");
gets(fuelmass);
validate_number();
} while (error != 0);
printf("\nRocket parameters entered: \n");
printf("\nTotal Impulse delivered: %s\n", totalimpulse);
printf("Average Impulse delivered: %s\n", averageimpulse);
printf("Time that ejection charge fires: %s\n", ejection);
printf("The mass of the empty vehicle: %sg\n", emptymass);
printf("The mass of the engine: %sg\n", enginemass);
printf("The mass of fuel: %sg\n", fuelmass);
char ans;
do
{
cout<< "\nLaunch simulation? (Y/N) : \n";
cout<< "You must type a 'Y' or an 'N'.\n";
cin >> ans;
}
while((ans !='Y')&&(ans !='N')&&(ans !='y')&&(ans !='n'));
if (ans == 'N')
{
getchar();
return 0;
}
else if (ans == 'Y')
{
// do something, calculations display page
return 0;
}
}
/************ Test all input in range 0 to 9 ****************/
void validate_number()
{
int errange = 0, numonly = 0, errlength = 0;
/********* validate numbers ********/
error = 0;
for (x = 0; x<strlen(totalimpulse); x++){
if (totalimpulse[x] >= '0' && totalimpulse[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(averageimpulse); x++){
if (averageimpulse[x] >= '0' && averageimpulse[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(ejection); x++){
if (ejection[x] >= '0' && ejection[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(emptymass); x++){
if (emptymass[x] >= '0' && emptymass[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(enginemass); x++){
if (enginemass[x] >= '0' && enginemass[x] <= '9'); else{
numonly++;
error++;
}
for (x = 0; x<strlen(fuelmass); x++){
if (fuelmass[x] >= '0' && fuelmass[x] <= '9'); else{
numonly++;
error++;
}
}
/********* validate range ********/
if (strlen(totalimpulse) <= 3){
x = atoi(totalimpulse);
if (x >= 0 && x <= 256)
;
else{
errange++;
error++;
}
}
else{
errlength++;
error++;
}
/**************** Report errors ******************/
if (error != 0){
if (numonly>0)
printf("\nOnly values in the range 0 to 9 are valid ");
if (errange>0)
printf("\nValue must be in the range 0 to 255");
if (errlength>0)
printf("\nMore than three values were entered");
}
I've counted 21 open braces and 21 closed braces which all seem to be positioned correctly yet I'm still getting the error, anything a fresh pair of eyes can help me with? I've counted the brackets so many times over that I'm going crazy.
It's a basic error for a basic problem but I'm just clueless as to what to change or add.
You have 27 open braces in the code.
[11:05am][wlynch#watermelon ~] fgrep -o '{' /tmp/asd.cc | wc -l
27
[11:05am][wlynch#watermelon ~] fgrep -o '}' /tmp/asd.cc | wc -l
21
Notably, there are two open braces in this piece of code, but only 1 closing brace:
for (x = 0; x<strlen(totalimpulse); x++){
if (totalimpulse[x] >= '0' && totalimpulse[x] <= '9'); else{
numonly++;
error++;
}
Additionally, this isn't invalid, but is awfully written:
if (averageimpulse[x] >= '0' && averageimpulse[x] <= '9'); else{
Please write it as:
if (not (averageimpulse[x] >= '0' && averageimpulse[x] <= '9')) {
or:
if (averageimpulse[x] < '0' || averageimpulse[x] > '9')) {
/*
Program to calculate trip and plan flights
*/
#define TRIP 6
#define NUMLEG 10
#include <stdio.h>
#include <string.h>
int input_trip(void);
int input_leg(int travel_leg[NUMLEG], int index);
char input_travel_type(char leg_type[TRIP][NUMLEG], int n, int index, int leg_num);
int main(void)
{
int row, col, trip_num, index, travel_leg[NUMLEG], leg_num, n;
char leg_type[TRIP][NUMLEG];
trip_num = input_trip();
for (index =0; index < trip_num; index++)
{
leg_num = input_leg(travel_leg,index);
printf("At Trip Number:%d\n", index);
printf("Number of legs %d\n", leg_num );
printf("A Airplane\n");
printf("R Train and rail travel\n");
printf("B Bus\n");
printf("C Car\n");
printf("F Ferry\n");
printf("S Cruise ship\n");
printf("M Motorcycle\n");
printf("Y Bicycle\n");
printf("T Boat other than a ferry or cruise ship\n");
printf("D Dirigible\n");
printf("O Other\n");
printf("NOTE!!:Please using capital letters (case sensitive).\n");
for (n = 0; n < leg_num; n ++)
{
printf("At leg Number%d\n", n);
input_travel_type(leg_type, n, index, leg_num);
}
}
for (index = 0; index < trip_num; index++)
{
printf("Trip#:%d Num_leg:%d ", index+1, travel_leg[index]);
for (n = 0; n < leg_num ; n++)
printf("Leg_type(#%d):%c ",n+1, leg_type[index][n]);
printf("\n");
}
return 0;
}
int input_trip(void)
{
int trip_num;
printf("Please enter the number of trips:");
scanf("%d", &trip_num);
// if( (trip_num <= TRIP) && (trip_num >= 3))
if( (trip_num <= TRIP) && (trip_num >=1) )
{
return trip_num;
}
else
{
while ((trip_num < 1) || ( trip_num > TRIP))
{
printf("Invalid number of trip. (Min of 3 trips and Max 6 trips).\n"); /*input number of trips*/
printf("Please enter the number of trips:");
scanf("%d", &trip_num);
if( (trip_num <= TRIP) && (trip_num >= 1))
{
return trip_num;
}
}
}
}
int input_leg(int travel_leg[NUMLEG], int index)
{
int leg_num, i;
char travel_type, checkA, A, R, B, C, F, S, M, Y, T, D, O;
printf("Please enter the number of legs in your trip:");
scanf("%d", &leg_num);
if ( (leg_num <= NUMLEG) && (leg_num > 0) )
{
travel_leg[index]=leg_num;
return leg_num;
}
else
{
while ( (leg_num < 0) || (leg_num > NUMLEG))
{
printf("Invalid number of legs(min 1 and max 10 legs).\n");
printf("Please enter the number of legs in your trip:");
scanf("%d", &leg_num);
if ( (leg_num <= NUMLEG) && (leg_num > 0) )
{
travel_leg[index]=leg_num;
return leg_num;
}
}
}
}
char input_travel_type(char leg_type[TRIP][NUMLEG], int n, int index, int leg_num)
{
char travel_type, checkA;
printf("Please enter the leg type for leg#%d:", n+1);
scanf("%c", &travel_type);
checkA = ( (travel_type == 'A') || (travel_type == 'R') || (travel_type == 'B') ||
(travel_type == 'C') || (travel_type == 'F') || (travel_type == 'S') ||
(travel_type == 'M') || (travel_type == 'Y') || (travel_type == 'T') ||
(travel_type == 'D') || (travel_type == '0') );
if (checkA == 1)
{
leg_type[index][n]=travel_type;
}
else
{
while (checkA != 1)
{
printf("Please enter the leg type for leg#%d:", n+1);
scanf("%c", &travel_type);
checkA = ( (travel_type == 'A') || (travel_type == 'R') || (travel_type == 'B') ||
(travel_type == 'C') || (travel_type == 'F') || (travel_type == 'S') ||
(travel_type == 'M') || (travel_type == 'Y') || (travel_type == 'T') ||
(travel_type == 'D') || (travel_type == '0') );
if (checkA == 1)
leg_type[index][n]=travel_type;
}
}
}
(I ask this question a while back but my code was too messy so I re-wrote it in functions so it was easier to read)
The problem I'm having is that my leg_num is getting over written every time I step out of the loop, so when I try to print out in the printf the last leg_num I put in is the number that is being use at:
for (n = 0; n < leg_num ; n++) the 2nd one in the printing loop
EDITED
So when I put in 2 trips trip# 1 has 3 legs trip# 2 has 2 legs when it runs through the printing loops it will only print 2 legs for each trip.
Trip#:1 Num_leg:3 Leg_type(#1):C Leg_type(#2):B
Trip#:2 Num_leg:2 Leg_type(#1):A Leg_type(#2):R
Trip#:1 Num_leg:1 Leg_type(#1):S Leg_type(#2):
Trip#:2 Num_leg:2 Leg_type(#1):F Leg_type(#2):S
Everything else works fine because I put printf statements along the way to check if that was the issue but it wasn't. I was thinking of saving the leg_num into a array and using that but not sure how to do it, plus the fact that this is part of a homework and our professor is restricting almost everything but the basic loops simple arrays.
printf("Trip#:%d Num_leg:%d ", index+1, travel_leg[index]);
for (n = 0; n < leg_num ; n++)
Change to
printf("Trip#:%d Num_leg:%d ", index+1, travel_leg[index]);
for (n = 0; n < travel_leg[index] ; n++)