-
unknown number of chars
I am writing this program that reads a string from a file. The thing is, it can be a whole sentence or whatever the user wants. How would I get an unknown number of chars? I don't want to use a character array, because then it would have to be something like string[1000] and that's just rediculous. But, if I use a char *, then I'm going to have to malloc the necessary amount of memory (therefore running into the same problem). I don't know how long the string will be!
Thanks.
--Garfield
-
A linked list
Code:
struct line_segment {
char buff[21];
struct line_segment *next;
};
Each stores up to 20 chars, and you string as many of these as necessary together, using malloc to allocate each one.
-
Also, why is 1000 bytes ridiculous? You're most likely programming on a system where you could allocate 20 megs of memory without a problem -- why nitpick on 1K? I often use a 5K buffer for programs that use buffers.
Honestly, as long as you're programming for 32-bit windows (console or GUI) you rarely need to worry about taking too much memory.
-
or you could use that thing that dean wrote a while back...went something like:
Code:
#include <stdio.h>
#include <malloc.h>
#include <conio.h>
int main(void)
{
char c, *input;
int x=0;
FILE *file;
input = (char *)malloc(1);
file = fopen("C:\File.txt", "r");
while(c != '~')
{
c = fgetch(file);
input[x] = c;
x++;
input = (char *)realloc(input, 1+x);
}
printf("\n%s\n",input);
getch();
free(input);
fclose(file);
return 0;
}
-
...of course that assumes that you put a ~ at the end of your file...
-
> A linked list
struct line_segment {
char buff[21];
struct line_segment *next;
};
Each stores up to 20 chars, and you string as many of these as necessary together, using malloc to allocate each one. <
I could do this, although how would I work through this? Would I implement it like this:
Code:
struct line_segment *line;
struct line_segment {
char buff[21];
struct line_segment *next;
};
fgets(line->buff, sizeof(line), fp);
But when I call fgets, that's where it gets confusing. Oh never mind, I'll just use getc, right? Then it'll be like this, right?:
Code:
for (x = 0; x < 21; ++x)
fgetc(line->buff[x], fp) // I'm not sure that the arguments of fgetc are correct
// I haven't used this function much
So, would fgetc be the function to use?
Thanks.
--Garfield
-
Cmon Garfield, I thought you'd got the hang of this
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SEG_LENGTH 21
typedef struct line_segment {
char buff[SEG_LENGTH];
struct line_segment *next;
} line_seg;
line_seg *append_line ( line_seg *head, char *buff ) {
// allocate (should check for NULL)
line_seg *temp = malloc( sizeof(line_seg) );
// copy data
strcpy( temp->buff, buff );
temp->next = NULL;
// append to linked list
if ( head == NULL ) {
head = temp;
} else {
line_seg *tail = head;
while ( tail->next != NULL ) {
tail = tail->next;
}
tail->next = temp;
}
return head;
}
void print_line ( line_seg *head ) {
while ( head != NULL ) {
printf( "%s\n", head->buff );
head = head->next;
}
}
int main ( ) {
line_seg *big_line = NULL;
char buff[SEG_LENGTH];
// read from stdin (or any FILE*)
while ( fgets(buff,SEG_LENGTH,stdin) != NULL ) {
big_line = append_line( big_line, buff );
if ( strchr( buff, '\n' ) != NULL ) break; // newline found
}
print_line( big_line );
// free big_line - easy exercise for the reader :)
return 0;
}
-
> Cmon Garfield, I thought you'd got the hang of this
I do have the hand...with linked lists. I never had to work with strings like this before. Thanks.
--Garfield
-
Code:
while ( fgets(buff,SEG_LENGTH,stdin) != NULL ) {
big_line = append_line( big_line, buff );
if ( strchr( buff, '\n' ) != NULL ) break; // newline found
}
Won't this not work, though? After all, fgets gets the string and then internally incrememts to read the next string on the next call, right? So, for every iteration, it's going to read a new line every time, right? Then it will only read 20 chars per line and then move on until the end of file. Am I understand this? Can you explain this code briefly, Salem? Thanks.
--Garfield
-
Code:
//______________________________________//
int find_max( char *filename )
{
FILE *fpp;
fpp = fopen(filename,"r") ;
fseek(fpp,0L,SEEK_END);
int filesize = ftell(fpp);
rewind(fpp);
char *buffer= (char *)malloc((sizeof (char )) * filesize);
fread(buffer,filesize,1,fpp);
fclose(fpp);
int count_max=0;
int max_sz=0;
int len=strlen(buffer);
char newline='\n';
int d;
for(d=0; d<len; d++)
{
if(isalpha(buffer[d]) || isdigit(buffer[d]) || isspace(buffer[d]) || isspunct(buffer[d]) && buffer[d] != newline)
{
count_max++;
}
else {
if(count_max > max_sz)
{
max_sz = count_max;
}
count_max=0;
}
}
free(buffer);
return max_sz;
}
//in main:
int num = find_max("my_file.txt");
char *buffer= (char *)malloc((sizeof (char )) * num);
// or if you don't wanna malloc:
char buffer[num];
-
Code:
/**
*** This code assumes the following:
*** 1) You pass it a valid, open, file pointer.
*** 2) You are at the point in the file where you want to read from.
*** 2) You pass it a postivie integer for the amount to read.
***/
char *fnread( FILE* fp, int n )
{
char *r = NULL,*s = NULL;
int x=0;
do
{
r = malloc( sizeof( char ) +1 );
r[0] = fgetc( fp );
r[1] = '\0';
r = realloc( r, strlen( s ) + 2 );
strncat( r, s, strlen( s ) + 2 );
s = r;
r = NULL;
}
while( !feof( fp ) && n > x++ );
return s;
}
I believe that should do the trick. I didn't bother compiling this one, but it's logic looks sound to me.
Quzah.
-
Genuis, quzah. Sheer genius. I didn't even think of reallocating to accomidate the whole string.
But, Salem (or anybody who can answer that), can you still explain my question about fgets and looping like that? It's really got me thinking. Thanks.
--Garfield
-
As I was browsing through comp.lang.c I came across this code to read in arbitary number of characters.
The cool thing about this code is that it mallocs just once , though it is a bit complicated .
http://www.iedu.com/mrd/c/getsm.c
-
Ug. That's nasty looking code. Can't you do the same thing this way:
Code:
char *fnread2( FILE*fp, int n )
{
char*c=NULL;
int x=0;
while( fgetc(fp) != EOF && x < n ) x++;
c = malloc( sizeof(char) * x + 1 );
fseek( fp, -x, SEEK_CUR );
fread( c, 1, x, fp );
c[x]='\0';
return c;
}
That should work. You probably could just fseek ahead n spaces, and if you didn't get an error, fseek back the same number, malloc that block, and fread. The onlything I'm not sure of, is if you fseek say 40 bytes, and there are only 20, how do you know how many are available, since fseek doesn't return the number of bytes foreward it seeks. I suppose you could actually ftell, fseek, ftell and subtract that number...
Quzah.
-
your program may or may not work for a file opened in the text mode
from K & R
int fseek(FILE *stream,long offset,int origin)
[bold]
For a text stream , offset must must be 0 , or a value returned by ftell ( in which case the origin must be SEEK_SET) .
[/bold]
also you reading all the characters in the file ( fgetc ) and not using them at all.