So I want to make kind of an encryption program for a school project,I want for example the letter 'a' to be replaced with:12345 'b' with 54321 in C,how can I accomplish this?I'm not the best,my code so far:
eFile = fopen("Message.txt", "ab+");
while(!feof(eFile))
{
fscanf(eFile,"%c",&message);
}
I want for example if I write the word apple into the text file,make the program scan it letter by letter and replace every letter with a 5 digit number(I have them predefined already) example: apple = 12342 69865 69865 31238 43297
read character by character from input
use simple array to convert between character to number or to string, or use a handler function for that
print that number
replacing is not easy, simplest way is to create a tempfile, write numbers to that tempfile, than copy the tempfile to the original file and remove tempfile.
_
#include <stdio.h>
#include <assert.h>
int cipher_table[255] = {
['a'] = 12342,
['p'] = 69865,
['l'] = 31238,
['e'] = 43297,
// so on...
};
int main()
{
FILE *fin = stdin; // fopen(..., "r");
assert(fin != NULL);
FILE *fout = stdout; // tmpfile();
assert(fout != NULL);
for (int c; (c = getc(fin)) != EOF;) {
if (c == '\n') {
if (fputc('\n', fout) == EOF) {
fprintf(stderr, "Error writing to file fout with fputc\n");
return -1;
}
continue;
}
if (fprintf(fout, "%5d ", cipher_table[c]) < 0) {
fprintf(stderr, "Error writing to file fout with fprintf\n");
return -1;
}
}
close(fin);
close(fout);
return 0;
}
I'm not sure if your strategy can be called encryption, but it can be easily accomplished
with a lookup table.
Simply put the replacements in an int table like so:
int map[]={ //size will be autoinferred to fit the indices
['a']=12342,
['p']=69865,
['l']=31238,
['e']=43297,
//you should preferrably have an entry for each value of char
};
And use it to print the replacements.
int c;
while(EOF!=(c=fgetc(inputFile)))
if(0>(outPutfile,"%d \n", map[c]))
return -1;
Since the size of the new file will unpredictably change, it'd probably
be a good idea to output into a temporary file and then move it in the
place of the original after it's successfully finished.
A better idea might be to simply forget about in-place file rewriting
and simply read stdin and write to stdout – that would allow the program to handle streams well as well and a possibly wrapper script could turn it into an inplace translator (via the temp file) after the fact if needed.
Related
I'm trying to do some simple tasks in C and run them from the command line in Linux.
I'm having some problems with both C and running the code from the command line with a given filename given as a parameter. I've never written code in C before.
Remove the even numbers from a file. The file name is transferred to
the program as a parameter in the command line. The program changes
this file.
How do I do these?
read from a file and write the results over the same file
read numbers and not digits from the file (ex: I need to be able to read "22" as a single input, not two separate chars containing "2")
give the filename through a parameter in Linux. (ex: ./main.c file.txt)
my attempt at writing the c code:
#include <stdio.h>
int main ()
{
FILE *f = fopen ("arr.txt", "r");
char c = getc (f);
int count = 0;
int arr[20];
while (c != EOF)
{
if(c % 2 != 0){
arr[count] = c;
count = count + 1;
}
c = getc (f);
}
for (int i=0; i<count; i++){
putchar(arr[i]);
}
fclose (f);
getchar ();
return 0;
}
Here's a complete program which meets your requirements:
write the results over the same file - It keeps a read and write position in the file and copies characters towards the file beginning in case numbers have been removed; at the end, the now shorter file has to be truncated. (Note that with large files, it will be more efficient to write to a second file.)
read numbers and not digits from the file - It is not necessary to read whole numbers, it suffices to store the write start position of a number (this can be done at every non-digit) and the parity of the last digit.
give the filename through a parameter - If you define int main(int argc, char *argv[]), the first parameter is in argv[1] if argc is at least 2.
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
if (argc < 2) return 1; // no argument given
FILE *f = fopen(argv[1], "rb+");
if (!f) return 1; // if fopen failed
// read, write and number position
long rpos = 0, wpos = 0, npos = 0;
int even = 0, c; // int to hold EOF
while (c = getc(f), c != EOF)
{
if (isdigit(c)) even = c%2 == 0;
else
{
if (even) wpos = npos, even = 0;
npos = wpos+1; // next may be number
}
fseek(f, wpos++, SEEK_SET);
putc(c, f);
fseek(f, ++rpos, SEEK_SET);
}
ftruncate(fileno(f), wpos); // shorten the file
}
I'd do that like this (removing extra declarations => micro optimizations)
/**
* Check if file is avaiable.
*/
if (f == NULL)
{
printf("File is not available \n");
}
else
{
/**
* Populate array with even numbers.
*/
while ((ch = fgetc(f)) != EOF)
ch % 2 != 0 ? push(arr, ch); : continue;
/**
* Write to file those numbers.
*/
for (int i = 0; i < 20; i++)
fprintf(f, "%s", arr[i]);
}
Push implementation:
void push(int el, int **arr)
{
int *arr_temp = *arr;
*arr = NULL;
*arr = (int*) malloc(sizeof(int)*(n - 1));
(*arr)[0] = el;
for(int i = 0; i < (int)n - 1; i++)
{
(*arr)[i + 1] = arr_temp[i];
}
}
In order to write to the same file, without closing and opening it, you should provide both methods, w+ (writing and reading), and this method will clear it's content.
So, change the line where you open the file, for this.
FILE *f = fopen ("arr.txt", "w+");
You should look for ways of implementing dynamic arrays (pointers and memory management).
With this example you could simply go ahead and write yourself, inside the main loop, a temporary variable that stores a sequence of numbers, and stack those values
Something like this (pseudocode, have fun :)):
DELIMITER one of (',' | '|' | '.' | etc);
char[] temp;
if(ch not DELIMITER)
push ch on temp;
else
push temp to arr and clear it's content;
Hope this was useful.
The software intends to read from a csv styled file (it's delimited by space not by a comma) and split the initial file into two new ones. The two files are determined by the last field, which is a binary value. As it stands, it currently reads the file character by character. I want it to recognize the space, and only run the individual character check on the very last field. To my understanding, strtok() will come in handy, but I'm struggling to find a way to incorporate that into the existing software.
Any help would be greatly appreciated :)
/*
* C program to parse a file, and split it into two based on the final line of input
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Function declarations */
int isMale(signed char _line);
int isFemale(signed char _line);
int isMale(signed char _line)
{
}
int isFemale(signed char _line)
{
}
int main()
{
/* File pointer to hold reference to different files */
FILE * fPtrIn, // Input file
* fPtrMale, // Males of school age
* fPtrFemale, // Females of school age
* fPtrMisc; // Data not within the given parameters
// current_char is the current character being read
// success stores the read status
char current_char;
int success;
// Open all files to perform read/write.
fPtrIn = fopen("data/example.txt", "r");
fPtrMale = fopen("data/males.txt" , "w");
fPtrFemale = fopen("data/females.txt" , "w");
fPtrMisc = fopen("data/erroneus.txt", "w");
// fopen() return NULL if unable to open file in given mode.
if(fPtrIn == NULL || fPtrMale == NULL || fPtrFemale == NULL || fPtrMisc == NULL)
{
// Unable to open file, exit software
printf("Unable to open file.\n");
printf("Please check whether file exists and you have read/write privilege.\n");
exit(EXIT_FAILURE);
}
// File open success message
printf("File opened successfully. \n\n");
// Read an integer and store read status in success.
while (fscanf(fPtrIn, "%d", ¤t_char) != -1)
{
// Write each one to separate file
if (isMale(current_char))
fprintf(fPtMale, "%d\n", current_char);
else if (isFemale(current_char))
fprintf(fPtrFemale, "%d\n", current_char);
else
fprintf(fPtrMisc, "%d\n", current_char);
}
// Done with all files, hence close all.
fclose(fPtrIn);
fclose(fPtrMale);
fclose(fPtrFemale);
fclose(fPtrMisc);
printf("Data written to files successfully.");
return 0;
}
You should
Read lines via fgets()
Copy the line read because strtok() will modify original buffer.
parse fields via strtok()
Judge and output according to the parsed field.
// hoping that too long lines won't come
char line[102400], line_parse[102400];
// Read an integer and store read status in success.
while (fgets(line, sizeof(line), fPtrIn) != NULL)
{
char *last_field, *ret;
// Copy the line for parsing
strcpy(line_parse, line);
// Separate the line into tokens
last_field = ret = strtok(line_parse, " ");
while (ret != NULL)
{
last_field = ret;
ret = strtok(NULL, " ");
}
// Get the first character of the last field
if (last_field == NULL) current_char = '\0'; else current_char = last_field[0];
// Write each one to separate file
if (isMale(current_char))
fputs(line, fPtrMale);
else if (isFemale(current_char))
fputs(line, fPtrFemale);
else
fputs(line, fPtrMisc);
}
So both the code to print the lines from the txt file and the code to count the lines in the txt file work fine when the other is commented out but when i try to have both work only the code that comes first works e.g. if i put the code to print out the lines first, the line count is always zero. However if i put the code to count the lines first, the number is correct but the lines from the txt file are not printed :S
#include <stdio.h>
int main(int argc, char const *argv[])
{
const int SIZE = 128;
char line[SIZE];
FILE *srcFile;
int c;
int count = 0; // Line counter (result)
if (argc == 1)
{
printf("No command line arguments given!\n");
return 1;
}
srcFile = fopen(argv[1], "r");
if (srcFile == NULL)
{
perror("\n*** FILE OPEN FAILED ***");
}
else
{
printf("\n*** FILE OPEN SUCCESSFUL ***\n\n");
}
while(fgets(line, SIZE, srcFile) != NULL)
{
printf("%s", line);
}
for (c = fgetc(srcFile); c != EOF; c = fgetc(srcFile))
{
if (c == '\n')
{
count ++;
}
}
if(c != '\n' && count != 0)
{
count ++;
}
printf("The file %s has %d lines\n ", argv[1], count);
fclose(srcFile);
return 0;
}
Here is a quick overview of how working with files is done in most programming languages:
When you open a file in a program you obtain a handle to that file. What the handle representation is depends on the language. In c it is the FILE structure. The handle contains - among other things - a file position indicator. Every read and write to that file through this handle happens at that position. Usually a read/write operation advances this file position indicator. Think about it: how do consecutive reads know to each read where the previous one left? You don't provide an argument to the read function telling it where to read from. You just "say" read. What happens is that each read call reads at the file position indicator and then advances this indicator, thus when the next read happens the handle has an updated file position indicator.
So the solution to your problem is - as mentioned in the comments - to put this position indicator to the beginning of the file. In c this can be done with rewind.
curious how the code fragment would have to look to include the line
count int the same loop as the print lines
Simple. Pseudocode:
line_count = 0
while (read line successful)
{
print line
increment line_count
}
print line_count
I have to develop a program in C that can have two kinds of inputs.
By feeding it a string ( I am assuming like this filename < String1234455678, please correct me if I am wrong).
By reading data from some file(s).
I have to do some checks regarding the characters that are in it and store them in an array. But I want to learn how to use the getc() from stdin first.
My first question is, can I use getc() in both cases?
I wanted to loop through every single character in the feed line/file, and I assume the code would look something like this:
char Array1[];
char charHolder;
//If the file/feed has chars (!NULL), execute
if ((charHolder = getchar())!=NULL){
//Do something
//Do some more
//Finally append to Array1
Array1[] = charHolder;
}
There might be some issues with the code above. I wanted to know if that kind of inserting is valid in C (with no index specified, which it will just push the value at the end of the array). Also, I read from http://beej.us/guide/bgc/output/html/multipage/getc.html that getc(stdin) and getchar() are exactly equivalent. I just want to double check that this is indeed true and either function will work with both my cases where I have to read data (from a file and feeding my program a string).
Also, I was wondering how I can achieve reading characters from multiple files. Say if my program was to be executed as programName file1 file2.
Thank you for your time and help!
Cheers!
Edit 1:
I also wanted to know how to check when the chars end from a file/string feed. Should I use the EOF for both cases?
Example:
while ((charHolder = getchar()) != EOF){
//code
}
Here is a sample:
#include <stdio.h>
void do_read(FILE * file, int abort_on_newline) {
char ch;
while (1) {
ch = getc(file);
if (ch == EOF) {
break;
}
if (abort_on_newline && ch == '\n') {
break;
}
printf("%c", ch);
}
}
int main(int argc, char * argv[])
{
int i = 1;
FILE * fp = NULL;
if (1 == argc) {
// read input string from stdin, abort on new line (in case of interactive input)
do_read (stdin, 1);
}
else {
// cycle through all files in command line arguments and read them
for (i=1; i < argc; i++) {
if ((fp = fopen(argv[i], "r")) == NULL) {
printf("Failed to open file.\n");
}
else {
do_read(fp,0);
fclose(fp);
}
}
}
return 0;
}
Use it like this:
To read from stdin: echo youstring | youprogram, or just start
yourprogram to get input from user
To read from file(s) yourprogram yourfile1 yourfile2 ...
Yes your can use getc in both cases, yes you should check for EOF in both cases, except for interactiv input. In case of binary files you also need to use feof function to check for EOF. See code above to read from multiple files.
I am taking a course on C and have been faced with the following task: 1. Load XCode and start a new C project. If you wish, remove
any extraneous code from the project so that you are left
with only what’s necessary to run the main function in your
project.
2. Prompt the user to enter two values-- the first a char
value of ‘D’ or ‘C’. The second value should be a floating
point value representing an amount of money.
3. As each value is entered record it to a text file that
saves it in the following format:
D, 250\n
C, 500\n
4. Test your program and examine the text file that it creates
to insure that it is in the required format.
5. Write a second program that assumes a starting balance of
$1,000.00 and outputs a completed ledger and final balance
for the account, adding or subtracting each entry from the
text file you previously created. Entries marked as a ‘C’
should be added to the account and entries marked as a ‘D’
should be debited (subtracted).
I have already created the file and am now onto step 5, I believe i know how to obtain the first character from the file to check if it is a 'c' or 'd', but after that i am not sure how to obtain the numerical value from the same line. How do I do this? This is my code so far(I am unsure what to put in the if/else if statements):
FILE *pFile = fopen("Users/Justin/Desktop/Ledger.txt", "r");
float startingBalance = 1000.00;
char action;
if(pFile != NULL)
{
while(!(feof(pFile)))
{
fgets(action, 1, pFile);
if(action == 'D' || action == 'd')
{
}
else if(action == 'C' || action == 'c')
{
}
else
printf("IO Error: Problem with file");
}
}
return 0;
}
Your file is organised in lines, so it's best to read it line-wise. The function for that is fgets, which will read a whole line of a certain maximum length into a char buffer. It keeps the terminating newline (unless the line is truncated because of the max length, but let's not deal with that right now). fgets returns the line buffer or NULL if the end of the file is reached.
Once you have a line, you must examine that line. Your lines all have the same syntax, namely
<action>, <amount>
so you could use sscanf, which isn't nice but quick and dirty. (scanfs error handling, for example, is very basic, so a good strategy is to ignore badly formatted lines altogether.)
The skeleton of your function might look like this:
int ledger(const char *fn)
{
FILE *f;
char line[80]; /* char buffer for line */
int lineno = 0; /* for error reporting */
f = fopen(fn, "r");
if (f == NULL) return -1; /* error */
while (fgets(line, sizeof(line), f)) {
char action;
double amount;
int n;
lineno++;
n = sscanf(line, " %c, %lf", &action, &amount);
if (n < 2) {
printf("Skipping badly formatted line %d\n", lineno);
continue;
}
/* Do stuff, e.g. just print */
printf("%c, %16.2f\n", action, amount);
}
fclose(f);
return 0; /* success */
}