Save a text file as a String in C - c

I want to save a text file as a String and then print it. Here's my code:
int lastLines(const char nameFileIn[], int nLines) {
char *text = 0;
FILE *inF; long length;
inF = fopen(nameFileIn, "r");
if (inF == NULL)
return -1;
fseek(inF, 0, SEEK_END);
length = ftell(inF);
fseek(inF, 0, SEEK_SET);
text = malloc(length + 1);
fread(text, length + 1, 1, inF);
fclose(inF);
text[length] = 0;
printf("%s", text);
free(text);
return 0; } /* lastLines */
int main(int argc, char** argv) {
char* nameFileIn = (argv[1]);
int nLines = atoi((argv[2]));
int num = lastLines(nameFileIn, nLines);
printf("\n%d\n", num);
return 1; } /* main */
Everything is alright 'till I add the second parameter in the command line (I'll need it in a postprocessing phase). At that time in my String there are a number of characters (equals to the number of lines in my file) which are not in my text file. Why?

Related

How to extract literally just 2 lines from a file

I am writing a program in C. I use low level functions like open, read, close. I have a file descriptor, etc, but I don't know how to print only the first 2 lines from a file that has e.g. 30 lines of text. how to do it?
you need to read a file into a string, iterate through the string, concat any character into the string variable, define a int variable for lines count, when lines reaches 2, break the loop
here’s an example how you can do it
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *get_first_two_lines(char *file_name) {
FILE *file = fopen(file_name, "r");
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char *buffer = malloc(size);
fread(buffer, 1, size, file);
char *two_lines = calloc(1, sizeof(char));
unsigned int lines = 0;
for (int i=0;i<strlen(buffer);i++) {
if (lines == 2) break;
if (buffer[i] == '\n') {
if (lines < 1) {
two_lines = realloc(two_lines, (strlen(two_lines) + 2) * sizeof(char));
strcat(two_lines, (char []) {'\n', 0});
}
lines++;
continue;
}
two_lines = realloc(two_lines, (strlen(two_lines) + 2) * sizeof(char));
strcat(two_lines, (char []) {buffer[i], 0});
}
return two_lines;
}
int main(int argc, char *argv[]) {
char *first_two_lines = get_first_two_lines("file_name");
printf("%s", first_two_lines);
return 0;
}

C program prints garbage values

My main problem is when i run the program it not work and a runnig time error is jumping on my screen. Can someone explain me whats the problem and help me?
*argv[i] is the adress and ignore the fact i don't have any free for my mallocs.
int main(int argc, char** argv)
{
FILE* file = 0;
file = fopen(argv[1], "r");
int numOfLines = countLines(file), i = 0, ch = 0, j = 0, flag = 0;
char** content;
content = (char**)malloc(numOfLines * sizeof(char*));
int* charsInLine = (int*)malloc(numOfLines * sizeof(int));
countCharsInLine(file, charsInLine);
fseek(file, 0, SEEK_SET);
for (i = 0; i < numOfLines; i++)
{
int lenOfFile = 0;
fseek(file, 0, SEEK_END);
lenOfFile = ftell(file);
content[i] = (char*)malloc(charsInLine[i] * sizeof(char) + 1);
content = fread(content, 1, lenOfFile, file);
}
for (i = 0; i < numOfLines; i++)
{
printf("%d string = %s", i,content[i]);
}
fclose(file);
getchar();
return 0;
}
I am going to assume countLines and countCharsInLine works correctly
Here is the updated code with comments
int main(int argc, char** argv)
{
FILE* file fopen(argv[1], "r");
if (file == NULL) {
// Output some error message
return EXIT_FAILURE;
}
int numOfLines = countLines(file); // I assume this rewinds.
char** content;
content = malloc(numOfLines * sizeof(char*)); // Do not need a cast
int* charsInLine = malloc(numOfLines * sizeof(int));
countCharsInLine(file, charsInLine);
rewind(file); // Easier to read the fseek
for (int i = 0; i < numOfLines; i++)
{
content[i] = malloc(charsInLine[i] + 1); // * sizeof(char) - Do not need this as sizeof(char) is defined as 1
// Reading one item of size charsInLine[i]
if (fread(content[i], charsInLine[i], 1, file) != 1) {
// Some error has occurred
fclose(file);
return EXIT_FAILURE;
}
content[i][charsInLine[i]] = 0; // Add null character
int ch = fgetc(file);
if (ch != '\n' && ch != EOF) { // Should be reading either the new line at the end of the line, or EOF
// Some error has occurred
fclose(file);
return EXIT_FAILURE;
}
}
fclose(file);
// Should free up the stuff that is malloced - I leave that up to you
return EXIT_SUCCESS;
}

Can't encrypt long string with XOR C crypter

I wrote a C program to perform an XOR encryption,
my problem is that the program is not able to encrypt files with more than 24 characters.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define BUF_SIZE 2
char* xor(char*, char*);
char* gen_key(size_t);
int main(int argc, char **argv) {
char *buffer = NULL,* encrypted_buffer = NULL;
size_t file_size;
char *key = gen_key(6);
char tmp_buffer[BUF_SIZE];
FILE *finput = NULL, *foutput = NULL;
finput = fopen("file.txt", "rb");
fseek(finput, 0, SEEK_END);
file_size = ftell(finput);
rewind(finput);
printf("File size : %d\n", (int)file_size);
buffer = (char*)malloc((file_size + 1) * sizeof(char));
memset(buffer, 0, sizeof(buffer));
while (!feof(finput)) {
memset(tmp_buffer, 0, sizeof(tmp_buffer));
fgets(tmp_buffer, sizeof(tmp_buffer), finput);
strcat(buffer, tmp_buffer);
}
printf("%s", buffer);
encrypted_buffer = xor(buffer, key);
free(buffer);
buffer = xor(encrypted_buffer, key);
printf("Encrypted : %s\n", encrypted_buffer);
printf("Decrypted : %s\n", buffer);
printf("EOF\n");
free(encrypted_buffer);
fclose(finput);
return 0;
}
char *gen_key(size_t length) {
srand(time(NULL));
const char charset[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz012345679";
const size_t charset_size = (sizeof(charset) - 1);
unsigned int i;
char *key = NULL;
key = (char*)malloc((length + 1) * sizeof(char));
memset(key, 0, sizeof(key));
for (i = 0; i < length; i++)
key[i] = charset[rand() % charset_size];
return key;
}
char *xor(char *file, char *key) {
unsigned int i;
char *xor = NULL;
xor = (char*)malloc(sizeof(file));
memset(xor, 0, sizeof(xor));
for (i = 0; i < strlen(file); i++)
*(xor + i) = *(file + i) ^ *(key + (i % strlen(key) - 1));
return xor;
}
And the output is :
File size : 55
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklimnopqrstuvwxyz
Encrypted : A2#G8- M >7S$1!
Decrypted : ABCDEFGHIJKLMNOPQRSTUVWX!:!e!
EOF
There are multiple problems in your code:
The buffer size is very small: #define BUF_SIZE 2. You should use a reasonable size for the line buffer, such as 80 or 100.
in memset(buffer, 0, sizeof(buffer));, buffer is a pointer, so sizeof(buffer) is not the size of the array, just the size of the pointer. Use file_size + 1 in this case.
You make the same mistake in other places in your code: pass the size of the buffers instead of relying on the sizeof() operator.
while (!feof(f)) is always wrong: you could jut use fread to read the file in one step or read line by line with:
while (fgets(tmp_buffer, sizeof(tmp_buffer), finput)) {
...
Note that there is a major problem with your approach: the key is composed of letters and digits and the file is assumed to contain text. If the file contains one of the characters in the key at the appropriate position, xoring this character with the key byte will produce a null byte that will stop the output in printf() and that would also stop the decryption if you were to store it in an output file. You rightfully use binary mode ("rb") for the file stream, but you should also make no assumptions on the file contents and handle null bytes transparently.
Here is a modified version of your program:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
unsigned char *xor(unsigned char *file, size_t size, const char *key);
char *gen_key(size_t length);
void print_buffer(const char *msg, unsigned char *buf, size_t size) {
printf("%s: ", msg);
for (size_t i = 0; i < size; i++) {
switch (buf[i]) {
case '\n':
printf("\\n");
break;
case '\\':
printf("\\\\");
break;
default:
if (buf[i] >= ' ' && buf[i] < 127)
putchar(buf[i]);
else
printf("\\%02x", buf[i]);
break;
}
}
printf("\n");
}
int main(int argc, char **argv) {
long file_size, nread, nwritten;
unsigned char *buffer, *encrypted_buffer, *decrypted_buffer;
char *key = gen_key(6);
FILE *finput = fopen("file.txt", "rb");
if (finput == NULL) {
fprintf(stderr, "cannot open file.txt: %s\n", strerror(errno));
return 1;
}
fseek(finput, 0, SEEK_END);
file_size = ftell(finput);
rewind(finput);
printf("File size: %ld\n", file_size);
buffer = calloc(file_size, sizeof(char));
nread = fread(buffer, 1, file_size, finput);
if (nread != file_size) {
fprintf(stderr, "error reading file.txt: read %ld bytes, expected %ld\n",
nread, file_size);
}
fclose(finput);
FILE *foutput = fopen("output.bin", "wb");
if (foutput == NULL) {
fprintf(stderr, "cannot open output.bin: %s\n", strerror(errno));
return 1;
}
encrypted_buffer = xor(buffer, nread, key);
nwritten = fwrite(encrypted_buffer, 1, nread, foutput);
if (nwritten != nread) {
fprintf(stderr, "error writing output.bin: wrote %ld bytes, expected %ld\n",
nwritten, nread);
}
fclose(foutput);
decrypted_buffer = xor(encrypted_buffer, nread, key);
printf("Key : %s\n", key);
print_buffer("Original ", buffer, nread);
print_buffer("Encrypted", encrypted_buffer, nread);
print_buffer("Decrypted", decrypted_buffer, nread);
if (!memcmp(decrypted_buffer, buffer, nread))
printf("OK\n");
free(decrypted_buffer);
free(encrypted_buffer);
free(buffer);
return 0;
}
char *gen_key(size_t length) {
const char charset[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz012345679";
const size_t charset_size = sizeof(charset) - 1;
char *key = (char*)calloc(length + 1, sizeof(char));
size_t i;
srand(time(NULL));
for (i = 0; i < length; i++)
key[i] = charset[rand() % charset_size];
return key;
}
unsigned char *xor(unsigned char *file, size_t size, const char *key) {
size_t i, keylen = strlen(key);
unsigned char *xor = calloc(size, sizeof(char));
for (i = 0; i < size; i++)
xor[i] = file[i] ^ key[i % keylen];
return xor;
}

Is it possible to traverse a file from bottom up? [C]

How can I traverse a file line by line going from the bottom up? For example, here is my code for traversing it from top to bottom:
void *readFileTB(char *str1)
{
int size = 1024;
char *buffer = malloc(size);
FILE *fp;
fp = fopen("testfile.txt", "r");
while(fgets(buffer, 1024, fp)) //get a line from a file
{
printf(buffer);
}
return 0;
}
If a file contains:
line1onetest
line2twotest
line3threetest
This function will print the following if executed:
line1onetest
line2twotest
line3threetest
How can I write a function that does the above but in the opposite direction so it outputs the following?
line3threetest
line2twotest
line1onetest
Any thoughts?
Line by line it's a little difficult. If we start with bytes, it's pretty simply: we first fseek to a little before the bottom:
if(fseek(fp, 256, SEEK_END) == -1) { /* handle error */ }
Since we've seeked 256 bytes before the end, we can read 256 bytes. Then we can seek back 256 more bytes, etc., until we hit the top of the file.
Now if you're trying to read lines of text, this can be tricky: you need to read a number of bytes at the end of the file and find the last newline character. If there is none, you didn't read enough and you need to read more. Once you've found it, your line starts there. To read the next line, you need to seek backwards again and don't go past your previous line start.
Here, I got a bit into it and coded the entire thing. I have no clue if it's any good, but at least you can get an idea of how it works. (I have a feeling there are better ways to do this)
To compile and use program:
$ gcc -Wall -o reverser main.c
Usage:
$ ./reverser text.txt
text.txt contents:
int main(int argc, char *argv[]){
if(argc != 2)
return 1;
print_rev_file(argv[1], 64);
return 0;
}
Results:
}
return 0;
print_rev_file(argv[1]);
return 1;
if(argc != 2)
int main(int argc, char *argv[]){
How to use in code:
main.c
#include <header.h>
int main(int argc, char *argv[]){
if(argc != 2)
return 1;
print_rev_file(argv[1], 64);
return 0;
}
header.h:
Note: It's bad form to use double underscore because many compilers use them.
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
///SUPPORT for get_line
size_t __file_size(FILE ** file); //It'd make sense to homogenize the parameters...
char * __get_line_copy(FILE ** file, size_t chunk_size, size_t position);
char * __get_line(int line_number, FILE ** file, size_t chunk_size);
size_t __nth_line(FILE ** file, int line_number, size_t chunk_size);
unsigned int __line_count(FILE ** file, size_t chunk_size);
#define file_size(x) __file_size(&x)
size_t __file_size(FILE ** file){
size_t old_pos = ftell(*file);
fseek(*file, 0, SEEK_END);
int file_size = ftell(*file);
fseek(*file, 0, old_pos);
return file_size;
}
char * __get_line_copy(FILE ** file, size_t chunk_size, size_t position){
int i;
char c;
char * buffer = malloc(chunk_size);
memset(buffer, 0, chunk_size);
size_t old_pos = ftell(*file);
fseek(*file, position, SEEK_SET);
for(i = 0; (i < chunk_size && (c = fgetc(*file)) != '\n' && !feof(*file)); i++){
*(buffer+i) = c;
}
*(buffer+chunk_size) = '\0';
fseek(*file, 0, old_pos);
return buffer;
}
#define FIRST 0
#define LAST -1
#define get_line(x, y, z) __get_line(x, &y, z);
char * __get_line(int line_number, FILE ** file, size_t chunk_size){
char * line = __get_line_copy(file, chunk_size, __nth_line(file, line_number, chunk_size));
return line;
}
size_t __nth_line(FILE ** file, int line_number, size_t chunk_size){
int i = 0, index;
size_t old_pos = ftell(*file);
fseek(*file, 0, SEEK_SET);
if(line_number > 0){
while(i <= line_number && !feof(*file)){
if(fgetc(*file) == '\n')
i++;
}
} else {
while(!feof(*file)){
if(fgetc(*file) == '\n')
i++;
}
index = i + (line_number+1);
fseek(*file, 0, SEEK_SET);
int i = 0;
while(i < index){
if(fgetc(*file) == '\n')
i++;
}
}
size_t position = ftell(*file);
fseek(*file, 0, old_pos);
return position;
}
#define line_count(x, y) __line_count(&x, y)
unsigned int __line_count(FILE ** file, size_t chunk_size){
int i = 1;
while(!feof(*file))
if(fgetc(*file) == '\n')
i++;
return i;
}
int print_rev_file(char * filename, size_t buffer){
FILE * file = fopen(filename, "r");
if(file == NULL){
return -1;
}
int i, lines = line_count(file, buffer);
for(i = 0; i < lines; i++){
char * line = get_line(LAST-i, file, buffer);
puts(line);
free(line);
}
return 0;
}
int main(int argc, char *argv[]){
if(argc != 2)
return 1;
print_rev_file(argv[1], 64);
return 0;
}
There's a utility in the GNU coreutils called tac that does exactly that.
You can view the source for it below.
http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob_plain;f=src/tac.c;hb=HEAD

need an example on easyzlib (how to compress and decompress strings sent in the argv from command line Windows/Linux)

OK now am half the way ,This is what i've done:
`int main(int argc,char* argv[]){
FILE *inputFile,*outputFile;
unsigned char *inputBuffer, *outputBuffer;
unsigned char *readMod = "r";
int result,x;
long int outputSize;
long int outputSizeun;
size_t inputSize;
if(argc >= 3){
inputFile = fopen(argv[2],readMod );
// get length of input
fseek(inputFile, 0, SEEK_END);
inputSize = ftell(inputFile);
fseek(inputFile, 0, SEEK_SET);
//allocate the inputBufer size
inputBuffer = (unsigned char *)malloc(inputSize);
fread(inputBuffer, 1, inputSize, inputFile);
outputSize = EZ_COMPRESSMAXDESTLENGTH(inputSize);
//allocate the outputBuffer size
outputBuffer = (unsigned char *)malloc(outputSize);
//check for the -z(compression)/-u(decompression) option s
if(strcmp("-z",argv[1])==0){
result = ezcompress(outputBuffer, &outputSize, inputBuffer, inputSize);
}else if(strcmp("-u",argv[1])==0){
result = ezuncompress(outputBuffer, &outputSizeun, inputBuffer, inputSize);
}else{
printf("Error : unknown operation \" %s \" type -z for compression or -u for decompression\n",argv[1]);
}
if (result == 0) {
// if the output filename was not present it output the compressed data into a file named "compress"
if(argv[3] == NULL){ argv[3] = "output";}
//write the output
outputFile = fopen(argv[3], "w");
fseek(outputFile, 0, SEEK_END);
fseek(outputFile, 0, SEEK_SET);
fwrite(outputBuffer, 1, outputSize, outputFile);
fclose(outputFile);
} else {
// Something went wrong
printf("%d ",result);
}
//now freeing buffers
free(inputBuffer);
free(outputBuffer);
}else{
printf("insufficnt Arguments :-s");
return 1;
}
return 0;
}
why does this code returns -3 when i run **a.exe -u output
ezcompress and ezuncompress work on the file data directly which are represented as arrays of characters.
for (int i = 1; i < argc; i++) {
// open argument you want to compress
FILE *inputFile = fopen(argv[i], "r");
// get length of input
// http://stackoverflow.com/questions/238603/how-can-i-get-a-files-size-in-c
fseek(inputFile, 0, SEEK_END);
size_t inputSize = ftell(inputFile);
fseek(inputFile, 0, SEEK_SET);
unsigned char *inputBuffer = (unsigned char *)malloc(inputSize);
fread(inputBuffer, 1, inputSize, inputFile);
long outputSize = EZ_COMPRESSMAXDESTLENGTH(sz);
unsigned char *outputBuffer = (unsigned char *)malloc(outputSize);
int result = ezcompress(outputBuffer, &outputSize, inputBuffer, inputSize);
if (result != EZ_BUF_ERROR) {
// Do stuff with outputBuffer which has length outputSize
} else {
// Something went wrong
}
free(intputBuffer);
free(outputBuffer);
}

Resources