How can I perfectly truncate a string in c? - 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

Related

In c, when I use %s to print out the contents of a char array it prints blank, but when I loop over it and print each character it works

Just implementing a simple sorting algorithm to sort a string. I tried printing out the buff char array with printf("%s\n") but it came out blank. The contents of the array are there, though, and I checked with printing out each character of it. What am I missing here?
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
if (argc != 2)
{
printf("usage: ./sortstring string");
exit(1);
}
int size = 1; // 1 to account for '\0'
for (int i = 0; argv[1][i] != '\0'; i++)
{
size += 1;
}
char buff[size];
strcpy(buff, argv[1]);
char temp;
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
if (tolower(buff[i]) > tolower(buff[j]))
{
temp = buff[i];
buff[i] = buff[j];
buff[j] = temp;
}
}
}
// printf("%s\n", buff);
for (int i = 0; i < size; i++)
{
printf("%c", buff[i]);
}
return 0;
}
Change "%c" to "%d" in printf and see the result.
for (int i = 0; i < size; i++)
{
printf("%d", buff[i]);
}
strcpy copies terminating null byte with the source string.
You sorted terminating null byte with other characters.
Your sorting function is probably sorting the null character to position 0.
Instead of attempting to manually count characters in "argc[1]", you could just use the "strlen" function. So, instead of
int size = 1; // 1 to account for '\0'
for (int i = 0; argv[1][i] != '\0'; i++)
{
size += 1;
}
You could use
int size = strlen(argv[1]);
Regards.
The problem is that you're initializing size with 1. I know you did that because you need one more char to \0, but after that, either you need to loop through size - 1 or you can decrease the value of size before your for loops.
Another thing you can do is: initialize size with 0, and use size + 1 while creating your array.

how to read integers from a string that are separated by space

in the text file it'll say something like this:
12 4 23 76
7 3 12 54
1 54 2 67
...
int arr[26];
int arr2[26];
int arr3[26];
int main(){
fp = fopen ("myfile.txt", "r");
while (fgets(store, sizeof(store), fp)){
//I tried using scanf but I couldn't get it to work
printf("%s", store); //prints out a line
}
}
I know that the 'store' has the string that I want to work with.
how can I grab the integers from 'store' that are separated by space and put them into an array?
so I would want
arr[0]=12 arr[1]=4 arr[2]=23 arr[3]=76,
arr2[0]=7 arr2[1]=3 arr2[2]=12 arr2[2]=65,
arr3[0]=1 arr3[1]=54 arr3[2]=2 arr3[3]=67
you can use strtok() and atoi() function if string format is guaranteed.
here's draft of code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int arr[3][26];
char store[100];
char *split;
int i, j;
int main(){
i = 0;
FILE* fp = fopen ("myfile.txt", "r");
while (fgets(store, sizeof(store), fp)){
printf("%s", store); //prints out a line
split = strtok(store, " ");
j = 0;
while(split) {
arr[i][j++] = atoi(split);
split = strtok(NULL, " ");
}
i++;
}
for(i = 0; i < 3; i++) {
for(j = 0; j < 4; j++) {
printf("%2d ", arr[i][j]);
}
puts("");
}
}
I hope that you can utilize this code for what you want.
-> I fixed code which is able to run.
you can modify this code because I tested and it worked.
I'm not sure which point you struggled, but I suggest you to check out how to use those functions in web.
the code posted by ChangHo is pretty accurate barring a few corrections.
Since the data contained in the text file, seems to contain blank lines, the primary fix is to ensure that these lines are ignored.
I notice in your comment, that when you try printing the vales after "strtok", you notice 0s.That's because the value of the variable "j" has been incremented....And is yet to be assigned a new value.....
arr[i][j++] = atoi(split);// j has been incremented
split = strtok(NULL, " ");
printf("%d\n", arr[i][j]);//displays 0,since "j" is yet to be assigned a value
All in all, here is the updated version of the code posted....
Please see the comments......
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int arr[3][26];
char store[100];
int i = 0;
int j = 0;
char *split;
int main(){
FILE *fp;
fp = fopen ("test.txt", "r");
while (fgets(store, sizeof(store), fp)){
if(strlen(store) == 1)//When fgets returns just the newline character
continue; //skip the line
printf("%s", store); //prints a line
split = strtok(store," ");
j = 0;
while(split != NULL){
arr[i][j] = atoi(split);
split = strtok(NULL," ");
printf("%d\n", arr[i][j]);//print value in array before j is incremented
j++;
}
arr[i][j] = '\0';//terminate the sub array with the NULL character
i++;
}
//print the result
for(int i = 0;i<3;++i){
for(int j = 0;arr[i][j] != '\0';++j)
printf("%d ",arr[i][j]);
putchar('\n');
}
fclose(fp);
}

Reading from a file, putting through an array and printing into file

I'm trying to make a program that translates words that are in a file and puts them in another file. Here I'm trying to read the words and put them into an array so I can search for them later and then print back into another file the translated word.
For the moment I'm trying to read and print from the array:
#include<stdio.h>
#include <string.h>
int main()
{
char rom_eng[4][2], fran_eng[4][2];
int i, j;
FILE* re = fopen("rom_eng.txt", "r");
FILE* out = fopen("out.txt", "w");
if (re == NULL)
{
printf("Error");
return 1;
}
for (i = 0; i < 2; i++)
{
for (j = 0; j < 4; j++)
fscanf(re, "%s", &rom_eng);
}
for (i = 0; i < 2; i++)
{
for (j = 0; j < 4; j++)
fprintf(out, "%s \n", rom_eng);
}
return 0;
}
The words in the file are like this:
- word word
- word word
The output is the same last word repeatedly printed in the out file.
You define : char rom_eng[4][2], fran_eng[4][2];
And then you read: fscanf(re, "%s", &rom_eng);
You 're not supposed to put the '&' before rom_eng because it is defined as a char, and chars are already pointers to adresses, so in this case you dont need to put the '&' to point to the adress.

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 ;)

Getting every other line empty on output

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.

Resources