C - making this program portable - c

The idea
scanning a password entered by the user and showing ********** in place of P#$$w00r_D
explaining the code
inside a while loop keep scanning the characters using getch() and put them into an array password[], until the user press return
The Code
#include <stdio.h>
#include <conio.h>
#define TRUE 1
#define P_MAX 25
int main(int argc, char* argv[]) {
char password[P_MAX], ch;
int i = 0;
puts("Enter the password [MAX 25]: ");
while (TRUE) {
if (i < 0) {
i = 0;
}//end if
ch = getch();
if (ch == 13)//return
break;
if (ch == 8) // BACKSPACE
{
putch('b');
putch(NULL);//Overwrite that character by NULL.
putch('b');
i--;//Decrement Current Track of Character. (i)
continue;
}//end if
password[i++] = ch;
ch = '*';
putch(ch);
}//end while
printf("\nPassword Entered : %s", password);//test
getch();
return 0;
}//end main
Compiling on Unix machine
[ar.lnx#host Documents] $ gcc 115.c -o x
115.c:2:18: fatal error: conio.h: No such file or directory
compilation terminated.
[ar.lnx#host Documents] $
this code works fine on windows, but not in Unix.
any help?

Related

Program is getting crashed when using getch and getche

#include <stdio.h>
#include <conio.h>
#define max 100
void compare(char *name,char* input);
int main()
{
int i=0;
char name[max]="santosh";
char input[max];
printf("enter the password\n");
while((input[i]=getchar())!='\n'){
i++;
}
input[i]='\0';
compare(name,input);
return 0;
}
void compare(char *name,char* input){
while((*name==*input)&&(*name!='\0'&&*input != '\0')){
*name++;
*input++;
}
if(*name=='\0'&&*input=='\0')
printf("Correct Password");
else
printf("Incorrect Password");
}
This Program is getting crashed in vs code but when I use getchar() instead of getch() or getche() all is working fine.
Why it is not working with getch() and how it will run as I want user to insert a password and thus want to use getch() not getchar().
First of all #define max generates a warning "macro redefinition", so change that.
The second problem is that getch() and getche do not convert the Enter key to 'newline' \n but to 'return' \r
The third problem is that instead of incrementing the pointers, you are incrementing what they point to.
Here is the corrected code:
#include <stdio.h>
#include <conio.h>
#define MAXX 100 // fixed macro name collision
void compare(char *name, char* input);
int main(void) // corrected definition
{
int i = 0;
char name[MAXX] = "santosh";
char input[MAXX];
printf("enter the password\n");
while((input[i] = getche()) != '\r') { // fixed '\n' check
i++;
}
input[i] = '\0';
compare(name, input);
return 0;
}
void compare(char *name,char* input){
while(*name == *input && *name != '\0' && *input != '\0') {
name++; // fixed pointer increment
input++; // fixed pointer increment
}
if(*name == '\0' && *input == '\0')
printf("Correct Password\n");
else
printf("Incorrect Password\n");
}
Finally you should also check i does not exceed the array bounds. The strings seem long enough, but not for players who try to break the program.

Problem with 2D char arrays, program does not print

I'm struggling with 2D char arrays, I want to create a list of trains, but it seems that something is wrong here since after I've registered 7 names the program will automatically close... Can somebody help me and explain me how to write the program correctly everytime? Thanks.
**NOTE:***the code is not finished yet*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 7
#define M 20
int main()
{ FILE *fp;
fp=fopen("Lines.txt","w");
int i,n;
char trains[N][M];
char train[M];
for(n=0;n<N;n++)
{
scanf("%s", train);
strncpy(trains[n],train,M-1);
}
for(n=0;n<N;n++)
{
for(i=0;i<M;i++)
{
printf("%s\n", trains[n][i]);
}
}
return 0;
}
having
char trains[N][M];
the printf in
for(i=0;i<M;i++)
{
printf("%s\n", trains[n][i]);
}
in invalid because trains[n][i] is a char and you print it as a string (%s)
All the form including the for can be replaced by
printf("%s\n", trains[n]);
Else you can write char by char but you need to stop when you reach the null char :
for(i=0; trains[n][i] != 0 ; i++)
{
printf("%c", trains[n][i]);
}
putchar('\n');
You open a file but you do not write in
You need to test the result of the fopen to check the file was open
Other problem in
scanf("%s", train);
strncpy(trains[n],train,M-1);
The strncpy does not copy the final null char
Because you have
char trains[N][M];
char train[M];
To use the intermediate train is useless and does not offer a protected (its size if not longer than trains[x])
You need to check the return value of scanf, and to read up to 19 characters (M - 1) you can do that :
if (scanf("%19s", trains[n]) != 1)
break;
You do not have the guarantee you read 7 trains so you have to change the loop after :
for (i = 0; i != n; ++i)
printf("%s\n", trains[n]);
You can also use puts in that case
And if you want to also write in the open file
for (i = 0; i != n; ++i) {
fprintf(sp, "%s\n", trains[n]);
puts(trains[n]);
}
Finally your program can be
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 7
#define M 20
int main()
{
FILE * fp=fopen("Lines.txt","w");
if (fp == 0) {
puts("cannot open Lines.txt");
return -1;
}
int i,n;
char trains[N][M];
for(n = 0; n<N; n++)
{
if (scanf("%19s", trains[n]) != 1)
break;
}
for(i = 0; i != n; ++i)
{
fprintf(fp, "%s\n", trains[i]);
/*puts(trains[i]);*/
}
fclose(fp);
return 0;
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -g -pedantic -Wextra c.c
pi#raspberrypi:/tmp $ ./a.out
train1
train2
train3
train4
train5
train6
train7
pi#raspberrypi:/tmp $ cat Lines.txt
train1
train2
train3
train4
train5
train6
train7
pi#raspberrypi:/tmp $
Note if the name of a train has more than 19 characters it will be cut, example :
pi#raspberrypi:/tmp $ ./a.out
train1
verylongnameofatrain
train3
train4
train5
train6
pi#raspberrypi:/tmp $ cat Lines.txt
train1
verylongnameofatrai
n
train3
train4
train5
train6
pi#raspberrypi:/tmp $
for(n=0;n<N;n++)
{
for(i=0;i<M;i++)
{
printf("%s\n", trains[n][i]);
}
}
should be
for(n=0;n<N;n++)
{
printf("%s\n", trains[n]);
}
This is because in your char array trains, each row contains the string entered by you. When you do trains[n][i], it tries to access a particular character inside the string.
If you want to print each character, try like below:
for(n=0;n<N;n++)
{
for(i=0;i<M && trains[n][i]!='\0';i++)
{
printf("%c", trains[n][i]);
}
printf("\n");
}

C - interact with terminal so that command is written on terminal but not executed

so i have
system("clear");
printf( "Enter a value :");`
int c = getchar();
which results in the terminal asking for a character this way
Enter a value:
What i want is the program to suggest a value as if the user had typed the value but didn't press enter, like this:
Enter a value: 5
Then the user can press enter and getchar() will receive 5 or backspace the 5 and input whatever value they want
Is this possible?
This is one way you can do it
#include <stdio.h>
#include <stdlib.h>
int main(){
char input[100] = "5";
int pos = 1;
int c_read = 0;
printf("Enter a value: 5");
while (1){
c_read = getch();
if (c_read == 13 || c_read == -1){
printf("\n");
break;
}
if (c_read == 8){
if(pos == 0)
continue;
pos--;
input[pos] = '\0';
printf("\b \b");
}else{
if (pos == 99)
continue;
printf("%c", c_read);
input[pos] = c_read;
pos++;
input[pos] = '\0';
}
}
printf("You entered %s\n", input);
}
Ofcourse this uses the god awful getch. You can find that in the ncurses library on Linux and comes with MinGW on windows.
You could replace getch with alternative implementation to read characters from the keyboard.
Also I am leaving it to you to convert the string to number before using.
PS: You might also have to put a fflush(stdout) after every print if it is being buffered for you and changes are not reflecting.

Anagram problems

I'm new to this forum and would like to seek help. I'm trying to modify an anagram program based on code from http://www.sanfoundry.com/c-program-...ings-anagrams/.
This time, however, I have used array pointers to obtain input from the user. I have also created a function "check_input" to ensure that the input consists of ONLY characters and excludes symbols(!, #, $). However, when I ran the program, it still accepts those symbols and does not break like I wanted it to. Please help.
Plus, I intend to make the program treat upper-case letters the same way as lower-case letters. Can this be achieved by using the "stricmp" function? If so, where should I place that function? Alternative methods are also appreciated.
Update: Sorry. I've added the check_input code at the bottom.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int test_anagram(char *ptrArray1, char *ptrArray2);
int check_input(char array1[], char array2[]);
int main()
{
char array1[100], array2[100];
char *pArray1, *pArray2;
int flag;
pArray1 = array1;
pArray2 = array2;
printf("Enter the first word: \n");
gets(pArray1);
printf("Enter the second word: \n");
gets(pArray2);
check_input(pArray1, pArray2);
flag = test_anagram(pArray1, pArray2);
if(flag == 1){
printf("\"%s\" and \"%s\" are anagrams.\n", pArray1, pArray2);
}else{
printf("\"%s\" and \"%s\" are not anagrams.\n", pArray1, pArray2);
}
return 0;
}
int test_anagram(char array1[], char array2[])
{
int num1[26] = {0}, num2[26] = {0}, i = 0;
while(array1[i] != '\0')
{
num1[array1[i] - 'a']++;
i++;
}
i = 0;
while(array2[i] != '\0')
{
num2[array2[i] - 'a']++;
i++;
}
for(i=0;i<26;i++)
{
if(num1[i] != num2[i]){
return 0;
}
return 1;
}
}
int check_input(char array1[], char array2[])
{
while(isalpha((int)array1) != 1){
break;
}
while(isalpha((int)array2) != 1){
break;
}
}
You haven't (yet) posted the full code of the check_input() function but one advice would be to validate the input when the user inputs every character.
You can do this using f.e. the getchar() function and checking if the inputted character is a letter, as well as converting it to the lowercase (or uppercase if you will).
You can do lowercase convertion like this:
#include <ctype.h>
// ...
tolower('A');

if else statement double printing C

I'm writing a program that adds line numbers to C files. I get the filenames as command line arguments but I wanted the user to have a chance to enter them if they forget to when they run the program. I ask the user to if they want to enter filenames and then they answer 'y' or 'n'. They are given five tries to answer correctly if an invalid character is entered but after five tries the program prints an error message and terminates. If the user enters an invalid character I have it print '[y/n]?' to the screen to prompt the user for those letters. If an invalid character is entered though it goes through the loop twice and prints them out side by side. Why does this happen?
Compiler.c file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lineNumAdderHeader.h"
#include "miscellaneousHeader.h"
#include "errorCheckedFunctionsHeader.h"
int main(int argc, char *argv[]){
int i = 1;
char ch;
int answerTries = 0;
char *seperatedFilenames[argc - 1];
if (argc < 2){
fprintf(stderr, "No files were entered for compiling.\n");
answer: do{
if (answerTries == 0)
printf("Would you like to enter files for compiling [y/n]? ");
else if (!(answerTries < 5))
fatal("in main(). An invalid character was entered too many times.");
else
printf("[y/n]? ");
ch = getchar();
if (ch == 'n' || ch == 'N')
exit(0);
answerTries++;
} while (ch != 'y' && ch != 'Y');
}
else{
while (i < argc){
seperatedFilenames[i - 1] = argv[i];
i++;
}
}
i = 0;
while (i < (argc - 1)){
lineNumAdder(seperatedFilenames[i]);
i++;
}
}
Fatal Funciton:
/*Displays a fatal error*/
void fatal(char *errorMessage){
/*Holds the errorMessage*/
char completedErrorMessage[strlen(errorMessage) + 17];
/*Copies the error message into completedErrorMessage*/
strcpy(completedErrorMessage, "[!!] Fatal Error ");
strcat(completedErrorMessage, errorMessage);
/*Prints the error message to the screen*/
fprintf(stderr, "%s\n", completedErrorMessage);
/*Exit the program in failure*/
exit(-1);
}
Your getchar() call returns one character from the standard input. When a users enters an answer, he then hits an enter/return key which translates to new line character which is part of the line that is then sent to standard input.
What you should probably do is to only check first character returned by getchar and then, in loop, read and discard all characters until you get new line character (\n). Only then, you can proceed to ask the question another time.
You should use this loop because your user may enter several characters at once. For example he may enter "yes" which will count as 4 characters.
Try flushing the stream before completing the loop, with
fflush(stdin);
If you don't want to use this function, you could try this,
do{
if(answerTries!=0) //it should clear your newline char input
getchar();
if (answerTries == 0)
printf("Would you like to enter files for compiling [y/n]? ");
else if (!(answerTries < 5))
fatal("in main(). An invalid character was entered too many times.");
else
printf("[y/n]? ");
ch = getchar();
if (ch == 'n' || ch == 'N')
exit(0);
answerTries++;
} while (ch != 'y' && ch != 'Y');
hope it helped..

Resources