Getting every other line empty on output - c

I have a problem with getting every other line empty on output with this code. The desired output is: http://paste.ubuntu.com/1354365/
While I get: http://paste.ubuntu.com/1356669/
Does anyone have an idea of why I'm getting these empty lines on every other line?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
FILE *fw;
int main(int argc, char *argv[]){
char buffer[100];
char *fileName = malloc(10*sizeof(char));
char **output = calloc(10, sizeof(char*));
char **outputBuffer = calloc(10, sizeof(char*));
fw = fopen("calvin.txt", "w+");
for(int y = 0; y < 6; y++){
for(int i = 0; i < 10; i ++)
{
output[i] = malloc(100);
}
for(int x = 0; x < 12; x++){
sprintf(fileName,"part_%02d-%02d", x, y);
fp = fopen(fileName, "rb");
if(fp == NULL)
{
printf("Kan ikke åpne den filen(finnes ikke/rettigheter)\n");
}
else if(fp != NULL){
memset(buffer, 0, 100);
for(int i = 0; i < 10; i++){
outputBuffer[i] = malloc(100);
}
fread(buffer, 1, 100, fp);
for(int i = 0; i < 100; i++){
if(buffer[i] == '\0')
{
buffer[i] = ' ';
}
else if(buffer[i] == '\n')
{
buffer[i] = ' ';
}
}
for(int i = 0; i < 10; i++) {
strncpy(outputBuffer[i], buffer + i * 10, 10);
strncat(output[i], outputBuffer[i]+1, 11);
}
}
}
for(int i = 0; i < 10; i++){
printf("%s\n", output[i]);
}
}
fclose(fp);
free(fileName);
}

You are not reading correcting from the file. On the first image in the beginning you have:
o ""oo " o o o
on the second
""oo o o o
That does not make a lot of sense because it is the first line. It is not related to empty lines since we are talking about the first line.
It seems that you are reading -2 characters from the left so " prints over o the other " on the ' ' ect..
Try this away, may not be the most efficient solution:
int read(char *file)
{
FILE *fp = NULL;
int size = 0, pos = 0,i;
fp = fopen(file,"r");
if (!fp) return 0;
for(; ((getc(fp))!=EOF); size++); // Count the number of elements in the file
fclose(fp);
char buffer[size];
fp = fopen(file,"r");
if (!fp) return 0;
while((buffer[pos++]=getc(fp))!=EOF); // Saving the chars into the buffer
for(i = 0; i < pos; i++) // print them.
printf("%c",buffer[i]);
fclose(fp);
return 1;
}

This part seems problematic:
strncpy(outputBuffer[i], buffer + i * 10, 10);
strncat(output[i], outputBuffer[i]+1, 11);
1) Why is it necessary to use the extra outputBuffer step?
2) You know that strncpy() isn't guaranteed to null-terminate the string it copies.
3) More significantly, output[i] hasn't been initialized, so strncat() will concatenate the string after whatever junk is already in there. If you use calloc() instead of malloc() when creating each output[i], that might help. It's even possible that your output[i] variables are what hold your extra newline.
4) Even if initialized to an empty string, you could easily overflow output[i], since you're looping 12 times and writing up to 11 characters to it. 11 * 12 + 1 for the null terminator = 133 bytes written to a 100-byte array.
In general, unless this is a class assignment that requires use of malloc(), I don't understand why you aren't just declaring your variables once, at the start of the program and zeroing them out at the start of each loop:
char fileName[10];
char output[10][100];
char outputBuffer[10][100];
And, as stated by others, your allocating a bunch of memory and not trying to free it up. Allocate it once outside of your loop or just skip the allocation step and declare them directly.

Related

Use a pointer to enter strings from a file into a 2D char array in C

I'm having trouble inputting strings from a file into my 2D char array (string array). I need to do it with pointers, however, it produces a weird jumble of the last and second to last words. Also, I cannot use the string library functions.
Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fin, *fout;
char lineRead[20], arr2[20][20];
int i, j, k, len;
fin = fopen("cp4in_1.txt","r");
if (fin){
while(fscanf(fin,"%s",&lineRead) != EOF){
char *pointer = lineRead;
for (k = 0; lineRead[k] != '\0'; k++);
for (i = 0; i < 4; i++){
for (j = 0; j < k; j++){
arr2[i][j] = *pointer;
pointer++;
}
}
}
}
else{
printf("Couldn't find file.\n");
}
}
Here is cp4in_1.txt:
ABCDE
PQRSTFG
acegikmoqsuwyz
bdfhjlnprtvx
The result I'm looking for should have arr2 contain an array of strings saying "ABCDE", "PQRSTFG", "acegikmoqsuwyz", and "bdfhjlnprtvx".
The main problem was that you were looping through arr[i] inside the while loop
And do not forget to place '\0' at the end of each string. Also, you were declaring char pointer several times inside the while loop, it is the error as well.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fpin, *fpout;
char lineRead[20], arr2[20][20], *pointer;
int i = 0, j, k, len;
fpin = fopen("cp4in_1.txt","r");
if (fpin){
while(fscanf(fpin,"%s", lineRead) != EOF){
pointer = lineRead;
for (k = 0; lineRead[k] != '\0'; k++);
for(j = 0; j < k; j++){
arr2[i][j] = *pointer;
pointer++;
}
arr2[i][j+1] = '\0';//place zero char at the end of the string
i++;
if(i >= 4)
break;
}
}
else{
printf("Couldn't find file.\n");
}
//output the result
for(i = 0; i < 4; i++){
printf("%s\n", arr2[i]);
}
return 0;
}
Output:
ABCDE
PQRSTFG
acegikmoqsuwyz
bdfhjlnprtvx
you should always terminate your string with \0 so:
for (i = 0; i < 4; i++){
for (j = 0; j < k; j++){
arr2[i][j] = *pointer;
pointer++;
}
arr2[i][j]='\0';
}
also your program need a little change
int main()
{
FILE* p;
p = fopen("file.txt", "r+");
int i = 0, j, k;
char* pointer, lineRead[20], arr2[20][20];
if (p != NULL)
{
while (!feof(p))
{
fscanf(p, "%s", &lineRead);
for (k = 0; lineRead[k] != '\0'; k++);
pointer = lineRead;
for (j = 0; j < k; j++)
{
arr2[i][j] = *pointer;
pointer++;
}
arr2[i][j] = '\0';
i++;
}
for (int i = 0; i < 4; i++)
{
printf("%s\n", arr2[i]);
}
}
else
{
printf("Couldn't find file.\n");
}
return 0;
}
The biggest issue you are facing is trying to do line-oriented input with a formatted-input function. (and you are using it wrong) Using fscanf (the scanf family of functions) is full of pitfalls for the new C programmer. Until you know what they are, avoid using them and instead use the line-oriented input functions fgets() or POSIX getline() which ensure an entire line of input is consumed each time.
In your case, the array lineRead decays to a pointer on access, C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3), so your use of &lineRead is wrong (resulting in parameter for fscanf() having type char ** instead of the correct char*). No '&' is required because lineRead is already a pointer, thus the correct use would be:
while(fscanf(fin,"%19s",lineRead) == 1){
(note: you must also provide the field-width modifier to limit the read of characters to what will fit in lineRead -- including the nul-terminating character. Otherwise you use of fscanf() is no more secure than using gets() -- which has been removed from C11 completely)
That is just one of the many pitfalls waiting to bite you using the scanf family.
Instead, using a line-oriented input function, you can do:
#include <stdio.h>
#define ROWS 20
#define COLS ROWS /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char arr[ROWS][COLS];
size_t n = 0;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
/* while array not full, read line into array */
while (n < ROWS && fgets (arr[n], COLS, fp)) {
char *p = arr[n]; /* pointer to start of string */
do { /* loop until '\n' found */
if (*p == '\n')
*p = 0; /* overwrite with nul-terminating char */
} while (*p && *++p);
n++; /* increment line counter */
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
for (size_t i = 0; i < n; i++) /* output stored lines */
printf ("line %2zu : %s\n", i, arr[i]);
}
Using a line-oriented input function, the '\n' is read from input and included in the buffer filled. Your only job is to remove the trailing '\n' from the buffer. This is normally done with, e.g. arr[n][strcspn(arr[n], "\n")] = 0;, but since you cannot use string.h a simple loop will work just fine.
Example Use/Output
With your input file in dat/cp4int_1.txt, you would pass the filename to the program as it's first argument and receive the following output:
$ ./bin/readcp4int_1 dat/cp4int_1.txt
line 0 : ABCDE
line 1 : PQRSTFG
line 2 : acegikmoqsuwyz
line 3 : bdfhjlnprtvx
Look things over and let me know if you have further questions.

Reading file word by word

I don't know why but my code prints a list of (null)(null)(null)....
I have to print the list of words from a file 'words.txt'.
Another question is: fscanf ignore white spaces?
#define WORD_LENGTH 1024
#define SIZE_QUOTE 100
int main(){
char **quote = malloc(sizeof(char*) * (size_t)SIZE_QUOTE);
long i;
for(i = 0; i < SIZE_QUOTE; i++){
if(!(malloc(sizeof(char) * (size_t)WORD_LENGTH)))
exit(1);
}
i = 0;
FILE *pf = fopen("words.txt", "r");
while(!feof(pf) && i < SIZE_QUOTE){
fscanf(pf, "%s", quote[i]);
printf("%s", quote[i]);
i++;
}
fclose(pf);
free(quote);
}
You're never assigning the return value of malloc() to quote[i] so they end up staying NULL (if you're lucky):
char **quote = malloc(sizeof(char*) * (size_t)SIZE_QUOTE);
long i;
for(i = 0; i < SIZE_QUOTE; i++){
if(!(malloc(sizeof(char) * WORD_LENGTH)))
It should be something like this instead:
char **quote = malloc(sizeof(char*) * (size_t)SIZE_QUOTE);
for(int i = 0; i < SIZE_QUOTE; i++){
quote[i] = malloc(sizeof(char) * WORD_LENGTH);
if(!quote[i])
Also you could avoid malloc() entirely and statically initialize that array if all the sizes are known:
char quote[SIZE_QUOTE][WORD_LENGTH] = {{'\0'}};
Also, you should be free()-ing the individual quote[i] at the end too:
for(int i = 0; i < SIZE_QUOTE; ++i) free(quote[i]);
free(quote);
There's other mistakes that have been pointed out through the comments already, so I won't elaborate further.

How can I perfectly truncate a string in c?

I am reading from a file of which each line is longer than 63 characters and I want the characters to be truncated at 63. However, it fails to truncate the lines read from the file.
In this program we are assuming that the file has 10 lines only:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char a[10][63];
char line[255];
int count = 0;
//Open file
FILE *fp;
fp = fopen("lines.dat", "r");
//Read each line from file to the "line array"
while(fgets(line, 255,fp) != NULL)
{
line[63] = '\0';
//copy the lines into "a array" char by char
int x;
for(x = 0; x < 64; ++x)
{
a[count][x] = line[x];
}
count++;
}
fclose(fp);
//Print all lines that have been copied to the "a array"
int i;
for(i = 0; i < 10; i++)
{
printf("%s", a[i]);
}
}
You have this result because you forgot to add the null string terminator in the end of a[0].
There's several ways to do it. My favorite one is to leave line as is: since it seems you want the truncated string elsewhere, you souldn't modify the source.
In that case, you can replace:
//Tries to truncate "line" to 20 characters
line[20] = '\0';
//copying line to each character at a time
int x;
for(x = 0; x < 20; x++)
{
a[0][x] = line[x];
}
with
//copying line to each character at a time
int x;
for(x = 0; x < 20; x++)
{
a[0][x] = line[x];
}
a[0][20] = 0;
i think you are missing the null byte.
You can get more info about this at : Null byte and arrays in C

Read a txt file with gets in C

I want to know what is the best option to read a txt file that contain two line of numbers using gets function in c and save them in an array within 1 second.
Assume the following example as an txt file called ooo.txt and it has the number 2.000.000 in the first line (which will be the size of the array) and 2.000.000 number in the second line that will be stored in the array.
Eg
2000000
59 595 45 492 89289 5 8959 (+1.999.993 numbers)
code i try (only the fcanf function)
int t_size;
fscanf(fp, "%d",&t_size); //bypass the first character!
int* my_array = NULL;
my_array = malloc(t_size*sizeof(*my_array));
if (my_array==NULL) {
printf("Error allocating memory!\n"); //print an error message
return 1; //return with failure
getchar();
}
int i =0;
for ( i = 0; i < t_size; i++ )
{
fscanf(fp, "%d",&my_array[i]); /*p[i] is the content of element at index i and &p[i] is the address of element at index i */
}
best, so far, code to make the procedure in 1 second
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <time.h>
int is_end(char* input) {
return *input == 0;
}
int is_linebreak(char* input) {
return *input == '\r' || *input == '\n' || *input == ' ';
}
char* eat_linebreaks(char* input) {
while (is_linebreak(input))
++input;
return input;
}
size_t count_lines(char* input) {
char* p = input;
size_t rows = 1;
if (is_end(p))
return 0;
while (!is_end(p)) {
if (is_linebreak(p)) {
++rows;
p = eat_linebreaks(p);
}
else {
++p;
}
}
return rows;
}
/* split string by lines */
char** get_lines(char* input, size_t line_count) {
char* p = input;
char* from = input;
size_t length = 0;
size_t line = 0;
int i;
char** lines = (char**)malloc(line_count * sizeof(char*));
do {
if (is_end(p) || is_linebreak(p)) {
lines[line] = (char*)malloc(length + 1);
for (i = 0; i < length; ++i)
lines[line][i] = *(from + i);
lines[line][length] = 0;
length = 0;
++line;
p = eat_linebreaks(p);
from = p;
}
else {
++length;
++p;
}
} while (!is_end(p));
// Copy the last line as well in case the input doesn't end in line-break
lines[line] = (char*)malloc(length + 1);
for (i = 0; i < length; ++i)
lines[line][i] = *(from + i);
lines[line][length] = 0;
++line;
return lines;
}
int main(int argc, char* argv[]) {
clock_t start;
unsigned long microseconds;
float seconds;
char** lines;
size_t size;
size_t number_of_rows;
int count;
int* my_array;
start = clock();
FILE *stream;
char *contents;
int fileSize = 0;
int i;
// Open file, find the size of it
stream = fopen(argv[1], "rb");
fseek(stream, 0L, SEEK_END);
fileSize = ftell(stream);
fseek(stream, 0L, SEEK_SET);
// Allocate space for the entire file content
contents = (char*)malloc(fileSize + 1);
// Stream file into memory
size = fread(contents, 1, fileSize, stream);
contents[size] = 0;
fclose(stream);
// Count rows in content
number_of_rows = count_lines(contents);
// Get array of char*, one for each line
lines = get_lines(contents, number_of_rows);
// Get the numbers out of the lines
count = atoi(lines[0]); // First row has count
my_array = (int*)malloc(count * sizeof(int));
for (i = 0; i < count; ++i) {
my_array[i] = atoi(lines[i + 1]);
}
microseconds = clock() - start;
seconds = microseconds / 1000000.0f;
printf("Took %fs", seconds);
return 0;
}
First of all, you will want to use fgets instead to avoid dangerous buffer overflows. Second, you want to remove all punctuation from your numbers. Thus 2.000.000 becomes 2000000. Then you can use pointers and the strtol function to convert characters to integers; there are also other functions to convert to floats and other types.
Since code wants speed and IO is a typically bottle-neck, reading the entire file at once after using fstat() to find its length (#Charlon) makes some sense. Following is a quick parsing of that buffer.
// Stream file into memory
size = fread(contents, 1, fileSize, stream);
contents[size] = 0;
fclose(stream);
#if 1
// new code
size_t array_n;
int n;
if (sscanf(contents, "%zu%n", &array_n, &n) != 1) Handle_BadInput();
my_array = malloc(array_n * sizeof *my_array);
if (my_array == NULL) Handle_OOM();
char *p = &contents[n];
errno = 0;
char *endptr;
for (size_t count = 0; count < array_n; count++) {
my_array[count] = strtol(p, &endptr, 10);
if (p == endptr || errno)
Handle_BadInput();
p = endptr;
}
char ch;
if (sscanf(p, " %c", &ch) == 1) Handle_ExtraInput();
#else
//old code
// Count rows in content
number_of_rows = count_lines(contents);
// Get array of char*, one for each line
lines = get_lines(contents, number_of_rows);
// Get the numbers out of the lines
count = atoi(lines[0]); // First row has count
my_array = (int*)malloc(count * sizeof(int));
for (i = 0; i < count; ++i) {
my_array[i] = atoi(lines[i + 1]);
}
#endif
Still prefer the scale-able approach of reading one number at a time.
The fastest way needs a lot of RAM :
1) open the file (man open)
2) use the fstat function to get the size of you file (man fstat)
3) read the file with a buffer malloc-ed with the size you just get at 2) (man malloc)
4) close the file (man close)
5) parse your buffer and transform each block of digits (each time until ' ' or '\0') to int
EDIT : if your RAM is not enough large, you need to create a get_next_int function that only stores in your buffer the next number in the file
EDIT 2 : You can read until you know the number of int you will need to store and compares this number with a security coef to the size of your ram, and use the good way so that your program won't set errno to ENOMEM if you know what I'm talking about ;)

C - Append to my array?

Real quick question, probably the time why I've forgotten such a basic thing!
I am capitalizing the first letter in an array, and I then want to append a 1 (to begin with onto the end) - I am generating word lists for WPA/2 networks as part of my Network Security research.
So, work out the length of the word, then, in the position in the array at the end of that word, place a number 1, or 2 ,or 3.
Totally forgotten how you do it though!
void capFirst(char *s, int i) {
s[0] = (toupper(s[0]));
}
int main(int argc, char** argv) {
int i;
char fileSave[256];
char myString[50];
FILE *fpIn, *fpOut;
for(i = 1; i < argc; i++) {
fpIn = fopen(argv[i], "rb");
snprintf(fileSave, 256, "%s~[%d]", argv[i], i);
fpOut= fopen(fileSave, "wb");
while((fgets(myString, 49, fpIn)) != NULL) {
if(isspace(myString[0]))
break;
i = strlen(myString);
if( (i > 8) && (i < 64) ) {
capFirst(myString, i);
fprintf(fpOut, "%s", myString);
}
}
}
return 0;
}
You would need
i = strlen(string);
string[i] = whatever you want there;
string[i+1] = 0;
But you have to ascertain that string has enough space for the 0-terminator.
By the way, you use i as the loop counter in the for loop as well as for the strlen inside that loop, that's generally a bad idea.

Resources