Printing all variants of a word - c

So here is the the program which i am trying to make:
Create password generator, which uses dictionary and match files to generate passwords by replacing letters in the dictionary words with their matches.
Example:
Dictionary file:
apple
loop
Match file:
a 4
e 3
o 0
Output:
4pple
appl3
4ppl3
l0op
lo0p
l00p
And this is my solution:
#include <stdio.h>
#include <string.h>
/* function prototypes */
int read_source(char* ,char* ,char* );
char* shift_string(char* ,char* );
int write_shifted(char* ,char* );
int main(int argc, char *argv[])
{
/* argv[1]: the source file with the original strings
* argv[2]: the shift file which indicates which characters are to be
* replaced with what
* argv[3]: the file in which the new strings are to be stored*/
if(!argv[1])
{
printf("No source file, can do nothing. Exiting.\n");
return 1;
}
else if (!argv[2])
{
printf("No shift file given, can do nothing. Exiting.\n");
return 2;
}
else if (!argv[3])
{
/* If no output file has been specified, print the
* output directly to the console. */
read_source(argv[1],argv[2],NULL);
return 0;
}
if (read_source(argv[1],argv[2],argv[3])!=0)
{
printf("There has been an error. Exiting.\n");
return 3;
}
if (argv[3])
{
printf("Everything seems to have gone according to plan.\n");
printf("Your output has been stored in \"%s\"\n",argv[3]);
}
return 0;
}
int read_source(char* source_file,char* shift_file,char* out_file)
{
FILE *file_pointer;
file_pointer=fopen(source_file, "r");
/* Exit gracefully if source_file cannot be found. */
if (file_pointer == NULL)
{
printf("Couldn't open \"%s\" for reading.\n",source_file);
return 1;
}
char* new_line;
/* maximum line length, can be changed if needed */
char line[256];
/* Go through the source file. */
while (fgets(line,sizeof line,file_pointer) != NULL)
{
new_line = shift_string(shift_file,line);
if (new_line==NULL)
{
printf("There has been an error with replacing the characters.\n");
return 2;
}
write_shifted(new_line,out_file);
}
int fclose(FILE *file_pointer);
return 0;
}
char* shift_string(char* shift_file,char* source_string)
{
/* This function replaces certain characters in a given source_string as
* specified by shift_file */
/* Open shift file. */
FILE *file_pointer;
char i,j;
file_pointer=fopen(shift_file, "r");
/* Exit gracefully if shift_file cannot be found. */
if (file_pointer == NULL)
{
printf("Couldn't open \"%s\" for reading.\n",shift_file);
return NULL;
}
int k;
/* Determine how long the source_string is for the loop below. */
int length = strlen(source_string);
while (fscanf(file_pointer, "%c %c\n", &i, &j)==2)
{
/* This loop actually does the replacing. */
for (k=0;k<length;k++)
{
if (source_string[k]==i)
{
source_string[k]=j;
}
}
}
int fclose(FILE *file_pointer);
return source_string;
}
int write_shifted(char* new_line,char* out_file)
{
/* This function writes the new strings to out_file
* If no out_file has been given, it will write the
* output to the console.*/
if (out_file==NULL)
{
printf("%s",new_line);
return 0;
}
FILE *file_pointer;
/* Open in a+ mode. If out_file does not yet exist, it will be created.
* If it does exist, it will be appended to instead of overwritten. */
file_pointer = fopen(out_file,"a+");
/* Write the new line */
fprintf(file_pointer,"%s",new_line);
fclose(file_pointer);
return 0;
}
So the problem is that now it prints only the final states (4ppl3 l00p) but i also need the middle states (4pple appl3 l0op lo0p). Can someone give me some clues how to make it. thanks in advance. :)

recursion works well for this type of problem. Basically, take whether or not to have the first letter substituted, and recurse with the rest of the word for each case - substituted and not substituted. Do this until you don't have any letters left, and you'll have all your combinations.
// terribly pseudo-codey, but should give the idea
string='abc';
stringfunction("", string);
// simplified, just shifts each letter by one
stringfunction(processed, unprocessed)
if unprocessed is empty
print processed
return
stringfunction(strcat(processed, unprocessed[0]), unprocessed[1]);
stringcunction(strcat(processed, unprocessed[0]+1), unprocessed[1]);
this will print out abc, abd, acc, acd, bbc, bbd, bcc, bcd
of course, for your case, instead of shifting the letter, you'd either do or not do the substitution.

Related

Create, read and print to stdout using C

This is my first time asking on Stack Overflow, i'll try my best to make a good question.
Fell free to correct me if i miss relevant information or stuff like that.
I'm writting a little program that creates a simple options menu.
My plan consist in very few steps:
Read file names from that macro #define file_dir "/home/me/dir"
Store that file names into names.txt.
I have to display the content of names.txt as options in my simple menu.
At the moment i was able to accomplish two of three steps but not so well i guess.
I create 2 function to do these 2 jobs. create_file(), read_file(), respectively.
Now is where my question really begins:
Each function works ok when i execute isolated. If i call as it intended to be
The second function read_file() instead to print the content of the file to stdout
it rewrite the names.txt and put a "square" character at the end of the file.
My plan is to redirect the return of the read_file() to an array.
So i can display as options in this bare bone menu.
Please help me understand.
Why i can't use this two functions like that ?
I know i am new to C and this program is far from be complete.
Here's my code:
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#define my_dir "/home/me/dir"
int roms_list;
int create_list()
{
/* redirect stdout to a file */
freopen("names.txt", "a+", stdout);
/* open dir and print their content */
DIR *dir;
struct dirent *ent;
if ((dir = opendir (nes_dir)) != NULL)
{
while ((ent = readdir (dir)) != NULL)
{
printf ("%s\n", ent->d_name);
}
}
closedir(dir);
close(names.txt);
}
int read_list()
{
FILE * list;
char ch;
list = fopen("names.txt", "r+");
if(NULL == list)
{
printf("file cant' be opened \n");
return 1;
}
do
{
ch = fgetc(list);
printf("%c", ch);
}
while (ch != EOF);
fclose(list);
}
int main()
{
create_list();
read_list();
return 0;
}
As MikeCAT points out, you attempt to printf("%c", ch); before checking ch != EOF resulting in attempting to print the int EOF values with the %c conversion specifier resulting in Undefined Behavior due to the mismatch in argument type and conversion specifier. ch must be type int to match the return type of fgetc() and to make a valid comparison with EOF.
If a conversion specification is invalid, the behavior is undefined.
If any argument is not the correct type for the corresponding
conversion specification, the behavior is undefined.
C11 Standard - 7.21.6.1(p9)
Additional Areas Where Your Code Needs Improvement
Your create_list() function is type int, but fails to return any value. Since create_list() can succeed or fail, it is imperative that the return type be able to communicate whether it succeeded or failed. Type int is fine, you can for example return 0; on a failure to read or on success, return the number of entries written to the file;
Your read_list() function is simply an output function that outputs the contents of the file written. While it can succeed or fail, it isn't critical to the continued operation of your program. Choosing type void for an output function is fine.
Do not hardcode file or directory names in functions. You shouldn't have to recompile your program just to read from a different directory or write to a different filename. Pass the directory to read and the filename to write as arguments to your program. That is what the arguments to main() are for, e.g. int main (int argc, char **argv). (or prompt the user to input both string values)
open your file in main() once and on successful open, pass a FILE* pointer for the open file stream to each of your functions as a parameter. You validate the open in main() because there is no need to call either function if fopen() fails.
pass the directory name to read to create_list() as a const char * parameter.
condition your call to read_list() on a successful return from create_list(). If create_list() fails, there is no need to call read_list().
Putting the improvements together, you could do something similar to the following:
#include <stdio.h>
#include <dirent.h>
/* returns 0 on failure, no. of files written on success */
int create_list (FILE *fp, const char *dname)
{
/* open dir and print their content */
DIR *dir;
struct dirent *ent;
int n = 0; /* simple counter for no. of entries read */
if ((dir = opendir (dname)) == NULL) { /* return 0 on failure to open */
return 0;
}
while ((ent = readdir (dir)) != NULL) {
/* skip dot files */
if ((ent->d_name[0] == '.' && !ent->d_name[1]) ||
(ent->d_name[0] == '.' && ent->d_name[1] == '.')) {
continue;
}
fprintf (fp, "%s\n", ent->d_name);
n++; /* increment counter */
}
closedir(dir);
return n; /* return the number of enteries written */
}
/* read list can be type void - it simply outputs contents of file */
void read_list (FILE *fp)
{
int ch; /* must be int */
while ((ch = fgetc (fp)) != EOF) { /* read char, validate not EOF */
putchar (ch); /* write to stdout */
}
}
int main (int argc, char **argv) {
char *dname, *fname; /* dirname and filename pointers */
int nfiles = 0; /* no. of files written */
FILE *fp = NULL; /* file pointer */
if (argc != 3) { /* validate 2 arguments given (dirname filename) */
fputs ("error: dirname and filename required\n"
"usage: ./program \"/path/to/files\" \"filename\"\n", stderr);
return 1;
}
dname = argv[1]; /* assign arguments to give descriptive names */
fname = argv[2]; /* (you could just use argv[x], a name helps) */
fp = fopen (fname, "w+"); /* open file for reading/writing */
if (!fp) { /* validate file open for reading/writing */
perror ("file open failed");
return 1;
}
/* validate create_list succeeds */
if ((nfiles = create_list (fp, dname))) {
printf ("%d files:\n\n", nfiles); /* number of entries in file */
rewind (fp); /* rewind file pointer */
read_list (fp); /* read list */
}
if (fclose (fp) != 0) { /* always validate close-after-write */
perror ("fclose fp");
}
}
Example Use/Output
You provide the directory to read as the first argument and the filename to write as the second. ./progname /path/to/read /file/to/write
A short example:
$ ./bin/dirlist_names ./km dat/dnames.txt
47 files:
startstop.o
kernelmod_hello1.c
.chardev.o.cmd
hello-4.o
.hello-2.mod.cmd
hello-2.mod
<snip>
hello-5.mod
.startstop.o.cmd
.hello-4.mod.cmd
chardev.mod
Makefile
hello-2.c
It looks like you are printing EOF. You should check if ch is EOF before printing that.
Also fgetc() returns int and convering the return value to char will prevent it from distinguishing EOF from one of valid byte, so you should use int instead of char for ch.
Instead of this:
char ch;
/* ... */
do
{
ch = fgetc(list);
printf("%c", ch);
}
while (ch != EOF);
You should use:
int ch;
/* ... */
while ((ch = fgetc(list)) != EOF)
{
printf("%c", ch);
}
Or:
int ch;
/* ... */
ch = fgetc(list);
while (ch != EOF)
{
printf("%c", ch);
ch = fgetc(list);
}

Matching text from 2 files

I have written a program that is designed to recover linux system passwords by searching for matching hashes which are present in two text files
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXCHAR 1000
//Declaring Functions to match word in file
int matchfile(char *shadowfilename, char*hashtablefilename);
//shadowfilename for shadow.txt hashtablefilename for hash table
void UsageInfo(char *shadowfile, char * hashtablefile );
//Display usage info on arguments for program
void UsageInfo(char *shadowfile, char * hashtablefile) {
printf("Usage: %s %s <shadowfile> <hashtable>\n", shadowfile,hashtablefile);
}
//main function.
int main(int argc, char *argv[]) {
int result, errcode;
//Display format for user to enter arguments and
//End program if user does not enter exactly 3 arguments
if(argc < 3 || argc > 3) {
UsageInfo(argv[1],argv[2]);
exit(1);
}
system("cls");
//Pass command line arguments into searchstringinfile
result = matchfile(argv[1], argv[2]);
//Display error message
if(result == -1) {
perror("Error");
printf("Error number = %d\n", errcode);
exit(1);
}
return(0);
}
//Declaring Functions to match word in file
//int matchfile(char *shadowfilename, char *hashtablefilename);
//shadowfilename for shadow.txt hashtablefilename for hash table
int matchfile(char *shadowfilename, char *hashtablefilename){
FILE *shadowfile;
FILE *hashtable;
char strshadow[MAXCHAR];
char strhash[MAXCHAR];
shadowfile = fopen(shadowfilename, "r");
if (shadowfile == NULL){
printf("Could not open file %s",shadowfilename);
return 1;
}
hashtable = fopen(hashtablefilename, "r");
if (hashtable == NULL){
printf("Could not open file %s",hashtablefilename);
return 1;
}
//Getting text from the 2 files
while (fgets(strshadow, MAXCHAR, shadowfile) != NULL &&fgets(strhash,MAXCHAR,
hashtable) != NULL){
printf("%s", strshadow);
printf("%s", strhash);
int linenumber = 1;
int search_result = 0;
//Matching words line-by-line
if((strstr(strshadow,strhash)) != NULL) {
//Display line in which matched word is found
printf("A match found on line: %d\n", linenumber);
printf("\n%s\n", strhash);
search_result++;
}
linenumber++;
}
fclose(shadowfile);
return 0;
}
However, I am unable to match the two hash values present in the two files due to the characters in front of them.
hashtable.txt.
This file contains the missing password in plain-text and is corresponding hash values.
The format is as follows: (password):(hash)
banana:$1$$Tnq7a6/C1wwyKyt0V/.BP/:17482:0:99999:7:::
shadow.txt. This file contains the account username in plain-text and is corresponding hash values.
The format is as follows: (user):(hash)
pyc1:$1$$Tnq7a6/C1wwyKyt0V/.BP/:17482:0:99999:7:::
As seen above, the words 'banana' and 'pyc1' prevent the program from detecting the two hashes from being detected.
Could someone tell me the changes I need to make to overcome this ?
Thank you.
Edit:Clarified format of shadow.txt and hashtable.txt
The simplest way to skip characters in string until some condition is met is:
char someString[MAXCHAR];
for (char* ptr = someString; *ptr != '\0'; ptr++) {
if (conditionIsMet(ptr)) {
doSomething();
break;
}
}
In your case, conditionIsMet(ptr) should be comparing *ptr to ':' and in that case, the password hash is under (ptr + 1) (string starting from the next character). I think you can write the rest of the code yourself.

C - Can't store file into an array of strings (based off line break)

I'm pretty new to C and someone "challenged" me to try and create a sorting program using C. I come from languages that are higher-level where doing something like this is easier, but I guess the lower-level intricacies are way over my head. I haven't implemented the sorting yet, because I've ran across an obstacle (just one of many) along the way.
Anyways, here is the code I have so far:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *unsortedFile; /* prepare file variable */
char lineBuffer[100]; /* prepare variable for each line */
char *listOfLines[100]; /* prepare line array variable to be sorted */
int n = 0;
int i;
if (argc == 2) /* if a file has been given */
{
unsortedFile = fopen(argv[1], "r"); /* open it readonly */
if (unsortedFile == NULL) /* if it couldn't open */
{
printf("Couldn't open the file %s\n", argv[1]);
printf("Does it exist?\n");
return -1; /* stop the program here, return non-zero for error */
}
printf("original file:\n\n");
while (fgets(lineBuffer, sizeof(lineBuffer), unsortedFile))
{
printf("%s", lineBuffer);
listOfLines[n] = lineBuffer; /* store line buffer to the array */
n = ++n; /* increase n for the next array element */
}
printf("\nLines to be sorted: %d\n", n);
for (i = 0; i < n; i++)
{
printf("%s", listOfLines[i]);
}
} else /* if no or too many args provided */
{
printf("\nArgument error - you either didn't supply a filename\n");
printf("or didn't surround the filename in quotes if it has spaces\n\n");
return -1; /* return non-zero for error */
}
}
At this point, you're probably busy vomiting over the messiest spaghetti code you've ever seen... but anyways, the issue occurs with that while statement, I guess. The original file prints to the console fine, but I don't think each line is being stored to listOfLines.
Here is what's in file.txt, the file I am supplying as an argument to the program:
zebra
red
abacus
banana
And here is the output of the program:
dustin#DESKTOP-033UL9B:/mnt/c/Users/Dustin/projects/c/sort$ ./sort file.txt
original file:
zebra
red
abacus
banana
Lines to be sorted: 4
banana
banana
banana
banana
dustin#DESKTOP-033UL9B:/mnt/c/Users/Dustin/projects/c/sort$
Looks like the last line of the file is the only one being stored to listOfLines? What could cause this behavior?
Thanks in advance!
listOfLines is an array of pointers. All those pointers are set to point to lineBuffer:
listOfLines[n] = lineBuffer;
And lineBuffer is repeatedly overwritten by lines from the file. The last line is banana, which is the final value of lineBuffer.
Your code then prints the values in listOfLines, which are all pointers to lineBuffer.
This line is very wrong, by the way (it has undefined behavior):
n = ++n;
If you want to increment n, that's either
n = n + 1;
or
++n;
Basically, don't modify the same variable twice within the same statement.
You need an array of char arrays (not array of pointers)
Switched:
char *lineOfLines[100]; // array of pointers
char listOfLines[100][100]; // array of char arrays
Then use strcpy.
Switched:
listOfLines[n] = lineBuffer;
strcpy(listOfLines[n], lineBuffer);
Working:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *unsortedFile; /* prepare file variable */
char lineBuffer[100]; /* prepare variable for each line */
char listOfLines[100][100]; /* prepare line array variable to be sorted */
int n = 0;
int i;
if (argc == 2) /* if a file has been given */
{
unsortedFile = fopen(argv[1], "r"); /* open it readonly */
if (unsortedFile == NULL) /* if it couldn't open */
{
printf("Couldn't open the file %s\n", argv[1]);
printf("Does it exist?\n");
return -1; /* stop the program here, return non-zero for error */
}
printf("original file:\n\n");
while (fgets(lineBuffer, sizeof(lineBuffer), unsortedFile))
{
printf("%s", lineBuffer);
strcpy(listOfLines[n], lineBuffer); /* store line buffer to the array */
n = n + 1; /* increase n for the next array element */
}
printf("\nLines to be sorted: %d\n", n);
for (i = 0; i < n; i++)
{
printf("%s", listOfLines[i]);
}
} else /* if no or too many args provided */
{
printf("\nArgument error - you either didn't supply a filename\n");
printf("or didn't surround the filename in quotes if it has spaces\n\n");
return -1; /* return non-zero for error */
}
}

Check if all char values are present in string

I'm currently working on this assignment and I'm stuck. The objective is to read a file and find if these char values exist in the String from the file. I have to compare a String from a file to another String I put in as an argument. However, just as long as each char value is in the String from the file then it "matches".
Example (input and output):
./a.out file1 done
done is in bonehead
done is not in doggie
Example (file1):
bonehead
doggie
As you can see the order in which is compares Strings does not matter and the file also follows one word per line. I've put together a program that finds if the char value is present in the other String but that is only part of the problem. Any idea how to go about this?
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv){
FILE *f = fopen(argv[1], "r");
char *line = NULL;
size_t len = 0;
ssize_t read;
char *word = argv[2];
if(argc != 3){
printf("./a.out <file> <word>\n");
exit(EXIT_SUCCESS);
}
if(f == NULL){
printf("file empty\n");
exit(EXIT_SUCCESS);
}
// confused what this loop does too
while((read = getline(&line, &len, f)) != -1){
char *c = line;
while(*c){
if(strchr(word, *c))
printf("can't spell \"%s\" without \"%s\"!\n", line, word);
else
printf("no \"%s\" in \"%s\".\n", word, line);
c++;
}
}
fclose(f);
exit(EXIT_SUCCESS);
}
Another approach would simply keep a sum of each character matched in the line read from the file, adding one for each unique character in the word supplied to test, and if the sum is equal to the length of the string made up by the unique characters is the search term, then each of the unique characters in the search term are included in the line read from the file.
#include <stdio.h>
#include <string.h>
#define MAXC 256
int main (int argc, char **argv) {
if (argc < 3 ) { /* validate required arguments */
fprintf (stderr, "error: insufficient input, usage: %s file string\n",
argv[0]);
return 1;
}
FILE *fp = fopen (argv[1], "r");
char line[MAXC] = "";
char *s = argv[2]; /* string holding search string */
size_t slen = strlen(s), sum = 0, ulen;
char uniq[slen+1]; /* unique characters in s */
if (!fp) { /* validate file open */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
memset (uniq, 0, slen+1); /* zero the VLA */
/* fill uniq with unique characters from s */
for (; *s; s++) if (!strchr (uniq, *s)) uniq[sum++] = *s;
ulen = strlen (uniq);
s = argv[2]; /* reset s */
while (fgets (line, MAXC, fp)) { /* for each line in file */
if (strlen (line) - 1 < ulen) { /* short line, continue */
printf ("%s is not in %s", s, line);
continue;
}
char *up = uniq; /* ptr to uniq */
sum = 0; /* reset sum */
while (*up) if (strchr (line, *up++)) sum++; /* count chars */
if (sum < ulen) /* validate sum */
printf ("%s is not in %s", s, line);
else
printf ("%s is in %s", s, line);
}
fclose (fp); /* close file */
return 0;
}
Example Use/Output
$ ./bin/strallcinc dat/words.txt done
done is in bonehead
done is not in doggie
which would work equally well for duplicate characters in the search string. e.g.
$ ./bin/strallcinc dat/words.txt doneddd
doneddd is in bonehead
doneddd is not in doggie
You can decide if you would handle duplicate characters differently, but you should make some determination on how that contingency will be addressed.
Let me know if you have any questions.
confused what this loop does
The while (read ... line obviously reads in lines from your file, placing them in the line variable
*c is a pointer to the start of the variable line and this pointer is incremented by c++, so that each letter in the word from the file is accessed. The while loop will be terminated when *c points to the null terminator (0).
The if (strchr(word ... line is testing if the test word contains one of the letters from the word in the file.
This seems to be the reverse of what you are trying to do - finding if all the letters in the test word can be found in the word from the file.
The printf lines are not sensible because there is no either/or - you need one line to print 'yes' our letters are present and one line to print 'no' at least one letter is not present.
The printf statements should be outside the comparison loop, so that you don't get multiple lines of output for each word. Add a flag to show if any letter does not exist in the word. Set flag to 1 at start, and only change it to 0 when a letter is not present, then use the flag to print one of the two outcome statements.
This code snippet may help
/* set flag to 'letters all present' */
int flag = 1;
/* set pointer c to start of input line */
c = word;
/* test word from file for each letter in test word */
while(*c) {
if(strchr(line, *c) == NULL) {
/* set flag to letter not present */
flag = 0;
break;
}
c++;
}

Debug Assertion Error in C

got some code here that won't compile correctly because it is saying that my pointer is already null when i am testing for a not null expression in my main function. here is the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCODE 53
#define MAXMESSAGE 256
void getCode(char *codeIn, char *filename) {
FILE *codeFile;
/* Open the file with the code */
codeFile = fopen(filename, "r");
if (codeFile == NULL) {
printf("Error opening the code file - program terminated\n");
exit(1);
}
/* Read the first (and assumed only) line from the file */
fgets(codeIn, MAXCODE, codeFile);
/* Terminate the string with /0 */
codeIn[MAXCODE] = '\0';
/* Close the file */
fclose(codeFile);
return;
}
int getMessage(int *message, char *filename) {
FILE *messageFile;
int counter = 0;
/* Open the file with the message */
messageFile = fopen(filename, "r");
if (messageFile == NULL) {
printf("Error opening the message file - program terminated\n");
exit(1);
}
/* Read one number at a time from the file and store it */
while (!feof (messageFile))
{
fscanf (messageFile, "%d", (message+counter));
counter++;
}
/* Close the file */
fclose(messageFile);
return (counter);
}
void sortMessage(int *message, int size) {
int i, j, temp;
for (i=0; i<size-1; i++) {
for (j=i; j<size; j++) {
if (message[i]>message[j]) {
temp = message[i];
message[i] = message[j];
message[j] = temp;
}
}
}
return;
}
void decodeMessage(char *codeIn, int *message, int size) {
FILE *outputFile;
int i = 0;
/* Open the output file */
outputFile = fopen("csis.txt", "w");
if (outputFile == NULL) {
printf("Error opening the output file - program terminated\n");
exit(1);
}
for (i=0; i< size; i++) {
fprintf(outputFile, "%c", codeIn[message[i]%100]);
printf("%c", codeIn[message[i]%100]);
}
printf("\n");
/* Close the file */
fclose(outputFile);
return;
}
int main(int argc, char *argv[])
{
char code[MAXCODE];
int msg[MAXMESSAGE];
int msgSize;
if (argc != 3) {
printf("This program takes two arguments: the name of the file with the code, and the name of the file with the encoded message\n");
}
getCode(code, argv[1]);
msgSize = getMessage(msg, argv[2]);
sortMessage(msg, msgSize);
decodeMessage(code, msg, msgSize);
return;
}
So basically my code is using two files called codefile.txt and msgfile.txt to decode the secret message and write the decoded sequence to a new text file called csis.
As woolstar pointed out in the comments, you don't need to NUL terminate your codeIn array following fgets, because fgets will do that for you. In fact, this constitutes an overflow which we can best see by considering what happens when MAXCODE is 1: codeIn contains only one element: codeIn[0], and accessing codeIn[1] is an error.
Similarly, since MAXCODE is 53 and that's how many elements pointed to by codeIn, codeIn[message[i]%100] is suspicious because there's a potential for message[i]%100 to be an invalid index. While we're on this note, it might be wise to make message[i] an unsigned int so that it can't be negative. The format specifier (for printf and scanf) corresponding to unsigned int is %u.
while ( !feof(messageFile) ) is wrong because the EOF flag isn't set until an attempt is made at reading. Between attempting to read and your EOF test, however, you've incremented counter which means you've counted one too many items. Perhaps your loop should look like this:
while (fscanf(messageFile, "%d", (message+counter)) == 1)
{
counter++;
}
Note that this code assumes you've chosen to keep message[i] as an int. If you've chosen to use unsigned int instead, of course you'll want to use the %u format specifier.
You can probably see that feof is mostly superfluous... You can usually test for erroneous reads by checking the return value. Try to avoid feof in the future.
Your main function has a return type of int, yet at the end of it you have a return; statement which doesn't return an int value. Remove that. It's probably causing errors during compilation.
Presumably, when argv != 3 you want to return from main so you don't end up processing invalid arguments... Make sure you return an int value, e.g.
if (argc != 3) {
printf("This program takes two arguments: the name of the file with the code, and the name of the file with the encoded message\n");
return 0;
}

Resources