reading data file into string using string tokenizer - structure

hi I have this code for reading text file into string
void addStu (BST_TREE* list)
{
// Local Declarations
COMPANY* stuPtr;
FILE* fp;
int i = 0;
char fileName[25];
char buffer [100];
char* tempString;
// Statements
stuPtr = (COMPANY*)malloc (sizeof (COMPANY));
stuPtr->name = (char*) malloc(128 * sizeof(char));
stuPtr->market = (char*) malloc(128 * sizeof(char));
stuPtr->initial = (char*) malloc(128 * sizeof(char));
tempString = (char*) malloc(128 * sizeof(char));
printf("Enter the file name: ");
gets(fileName);
fp = fopen(fileName, "r");
if(fp == NULL)
{
printf("Error cannot open the file!\n");
exit(101);
}
while(fgets(buffer, 100, fp) != NULL)
{
if (!stuPtr)
printf("MEmory overflow!\n"), exit(101);
tempString = buffer;
stuPtr->name = strtok(tempString, ";");
sscanf(buffer, "%15s %15s %f ", stuPtr->market, stuPtr->initial, &(stuPtr->stock));
BST_Insert(list, stuPtr);
i++;
} // end while
} //addStu
this code does not work properly since buffer keep on changing when i didn't even modify it
this is my input
Microsoft Corporation; NASDAQ MSFT 259.94B
Yahoo! Inc.; NASDAQ YHOO 37.67B
Baidu.com, Inc. (ADR); NASDAQ BIDU 8.64B
CNET Networks, Inc.; NASDAQ CNET 1.13B
QuickLogic Corporation; NASDAQ QUIK 88.62M
Answers Corporation; NASDAQ ANSW 53.49M
Apple Inc.; NASDAQ AAPL 114.17B
for example when I tried to read the first line, i was able to get stuPtr->name to contain Microsoft Coporation using string token, after this point the tempString would be modify to contain Microsoft Coporation as well, for some reason the buffer that was not suppose to change, changed as well leading to stuPtr->market, stuPtr->initial, and stuPtr->stock have the wrong input value.
why did buffer change without being modify? how can I fix this code to make it work ?
thank in advance for helping

strtok() has unexpected side-effect for OP.
After stuPtr->name = strtok(tempString, ";");, the buffer location formerly occupied by the ';' is replaced by a '\0'. So when sscanf(buffer, "%15s ... is called, unexpected results occur. Recommendation: consider alternatives other than mixing strtok() and 'sscanf()`.
One could continue on using sccanf() with
sscanf(&buffer[strlen(stuPtr->name)+1], "%15s ...
But recommend a sscanf() only solution or a strtok(), strtof().

Related

How can I read \x1a from a file? [duplicate]

I am attempting to write a bittorrent client. In order to parse the file etc. I need to read a torrent file into memory. I have noticed that fread is not reading the entire file into my buffer. After further investigation it appears that whenever the symbol shown below is encountered in the file, fread stops reading the file. Calling the feof function on the FILE* pointer returns 16 indicating that the end of file has been reached. This occurs no matter where the symbol is placed. Can somebody explain why this happens and any solutions that may work.
The symbol is highlighted below:
Here is the code that does the read operation:
char *read_file(const char *file, long long *len){
struct stat st;
char *ret = NULL;
FILE *fp;
//store the size/length of the file
if(stat(file, &st)){
return ret;
}
*len = st.st_size;
//open a stream to the specified file
fp = fopen(file, "r");
if(!fp){
return ret;
}
//allocate space in the buffer for the file
ret = (char*)malloc(*len);
if(!ret){
return NULL;
}
//Break down the call to fread into smaller chunks
//to account for a known bug which causes fread to
//behave strangely with large files
//Read the file into the buffer
//fread(ret, 1, *len, fp);
if(*len > 10000){
char *retTemp = NULL;
retTemp = ret;
int remaining = *len;
int read = 0, error = 0;
while(remaining > 1000){
read = fread(retTemp, 1, 1000, fp);
if(read < 1000){
error = feof(fp);
if(error != 0){
printf("Error: %d\n", error);
}
}
retTemp += 1000;
remaining -= 1000;
}
fread(retTemp, 1, remaining, fp);
} else {
fread(ret, 1, *len, fp);
}
//cleanup by closing the file stream
fclose(fp);
return ret;
}
Thank you for your time :)
Your question is oddly relevant as I recently ran into this problem in an application here at work last week!
The ASCII value of this character is decimal 26 (0x1A, \SUB, SUBSTITUTE). This is used to represent the CTRL+Z key sequence or an End-of-File marker.
Change your fopen mode ("In [Text] mode, CTRL+Z is interpreted as an end-of-file character on input.") to get around this on Windows:
fp = fopen(file, "rb"); /* b for 'binary', disables Text-mode translations */
You should open the file in binary mode. Some platforms, in text (default) mode, interpret some bytes as being physical end of file markers.
You're opening the file in text rather than raw/binary mode - the arrow is ASCII for EOF. Specify "rb" rather than just "r" for your fopen call.

Webm (VP8 / Opus) file read and write back

I am trying to develop a webrtc simulator in C/C++. For media handling, I plan to use libav. I am thinking of below steps to realize media exchange between two webrtc simulator. Say I have two webrtc simulators A and B.
Read media at A from a input webm file using av_read_frame api.
I assume I will get the encoded media (audio / video) data, am I correct here?
Send the encoded media data to simulator B over a UDP socket.
Simulator B receives the media data in UDP socket as RTP packets.
Simulator B extracts audio/video data from just received RTP packet.
I assume the extracted media data at simulator B are the encoded data only (am I correct here). I do not want to decode it. I want to write it to a file. Later I will play the file to check if I have done everything right.
To simplify this problem lets take out UDP socket part. Then my question reduces to read data from a webm input file, get the encoded media, prepare the packet and write to a output file using av_interleaved_write_frame or any other appropriate api. All these things I want to do using libav.
Is there any example code I can refer.
Or can somebody please guide me to develop it.
I am trying with a test program. As a first step, my aim is to read from a file and write to an output file. I have below code, but it is not working properly.
//#define _AUDIO_WRITE_ENABLED_
#include "libavutil/imgutils.h"
#include "libavutil/samplefmt.h"
#include "libavformat/avformat.h"
static AVPacket pkt;
static AVFormatContext *fmt_ctx = NULL;
static AVFormatContext *av_format_context = NULL;
static AVOutputFormat *av_output_format = NULL;
static AVCodec *video_codec = NULL;
static AVStream *video_stream = NULL;
static AVCodec *audio_codec = NULL;
static AVStream *audio_stream = NULL;
static const char *src_filename = NULL;
static const char *dst_filename = NULL;
int main (int argc, char **argv)
{
int ret = 0;
int index = 0;
if (argc != 3)
{
printf("Usage: ./webm input_video_file output_video_file \n");
exit(0);
}
src_filename = argv[1];
dst_filename = argv[2];
printf("Source file = %s , Destination file = %s\n", src_filename, dst_filename);
av_register_all();
/* open input file, and allocate format context */
if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0)
{
fprintf(stderr, "Could not open source file %s\n", src_filename);
exit(1);
}
/* retrieve stream information */
if (avformat_find_stream_info(fmt_ctx, NULL) < 0)
{
fprintf(stderr, "Could not find stream information\n");
exit(2);
}
av_output_format = av_guess_format(NULL, dst_filename, NULL);
if(!av_output_format)
{
fprintf(stderr, "Could not guess output file format\n");
exit(3);
}
av_output_format->audio_codec = AV_CODEC_ID_VORBIS;
av_output_format->video_codec = AV_CODEC_ID_VP8;
av_format_context = avformat_alloc_context();
if(!av_format_context)
{
fprintf(stderr, "Could not allocation av format context\n");
exit(4);
}
av_format_context->oformat = av_output_format;
strcpy(av_format_context->filename, dst_filename);
video_codec = avcodec_find_encoder(av_output_format->video_codec);
if (!video_codec)
{
fprintf(stderr, "Codec not found\n");
exit(5);
}
video_stream = avformat_new_stream(av_format_context, video_codec);
if (!video_stream)
{
fprintf(stderr, "Could not alloc stream\n");
exit(6);
}
avcodec_get_context_defaults3(video_stream->codec, video_codec);
video_stream->codec->codec_id = AV_CODEC_ID_VP8;
video_stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
video_stream->time_base = (AVRational) {1, 30};
video_stream->codec->width = 640;
video_stream->codec->height = 480;
video_stream->codec->pix_fmt = PIX_FMT_YUV420P;
video_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
video_stream->codec->bit_rate = 400000;
video_stream->codec->gop_size = 10;
video_stream->codec->max_b_frames=1;
#ifdef _AUDIO_WRITE_ENABLED_
audio_codec = avcodec_find_encoder(av_output_format->audio_codec);
if (!audio_codec)
{
fprintf(stderr, "Codec not found audio codec\n");
exit(5);
}
audio_stream = avformat_new_stream(av_format_context, audio_codec);
if (!audio_stream)
{
fprintf(stderr, "Could not alloc stream for audio\n");
exit(6);
}
avcodec_get_context_defaults3(audio_stream->codec, audio_codec);
audio_stream->codec->codec_id = AV_CODEC_ID_VORBIS;
audio_stream->codec->codec_type = AVMEDIA_TYPE_AUDIO;
audio_stream->time_base = (AVRational) {1, 30};
audio_stream->codec->sample_rate = 8000;
audio_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
if(!(av_output_format->flags & AVFMT_NOFILE))
{
if (avio_open(&av_format_context->pb, dst_filename, AVIO_FLAG_WRITE) < 0)
{
fprintf(stderr, "Could not open '%s'\n", dst_filename);
}
}
/* Before avformat_write_header set the stream */
avformat_write_header(av_format_context, NULL);
/* initialize packet, set data to NULL, let the demuxer fill it */
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
pkt.stream_index = video_stream->index;
ret = av_read_frame(fmt_ctx, &pkt);
while (ret >= 0)
{
index++;
//pkt.stream_index = video_avstream->index;
if(pkt.stream_index == video_stream->index)
{
printf("Video: Read cycle %d, bytes read = %d, pkt stream index=%d\n", index, pkt.size, pkt.stream_index);
av_write_frame(av_format_context, &pkt);
}
#ifdef _AUDIO_WRITE_ENABLED_
else if(pkt.stream_index == audio_stream->index)
{
printf("Audio: Read cycle %d, bytes read = %d, pkt stream index=%d\n", index, pkt.size, pkt.stream_index);
av_write_frame(av_format_context, &pkt);
}
#endif
av_free_packet(&pkt);
ret = av_read_frame(fmt_ctx, &pkt);
}
av_write_trailer(av_format_context);
/** Exit procedure starts */
avformat_close_input(&fmt_ctx);
avformat_free_context(av_format_context);
return 0;
}
When I execute this program, it outputs "codec not found". Now sure whats going wrong, Can somebody help please.
Codec not found issue is resolved by separately building libvpx1.4 version. Still struggling to read from source file, and writing to a destination file.
EDIT 1: After code modification, only video stuff I am able to write to a file, though some more errors are still present.
EDIT 2: With modified code (2nd round), I see video frames are written properly. For audio frames I added the code under a macro _AUDIO_WRITE_ENABLED_ , but if I enable this macro program crashing. Can somebody guide whats wrong in audio write part (code under macro _AUDIO_WRITE_ENABLED_).
I am not fully answering your question, but I hope we will get to the final solution eventually. When I tried to run your code, I got this error "time base not set".
Time base and other header specs are part of codec. This is, how I have this thing specified for writing into file (vStream is of AVStream):
#if LIBAVCODEC_VER_AT_LEAST(53, 21)
avcodec_get_context_defaults3(rc->vStream->codec, AVMEDIA_TYPE_VIDEO);
#else
avcodec_get_context_defaults2(rc->vStream->codec, AVMEDIA_TYPE_VIDEO);
#endif
#if LIBAVCODEC_VER_AT_LEAST(54, 25)
vStream->codec->codec_id = AV_CODEC_ID_VP8;
#else
vStream->codec->codec_id = CODEC_ID_VP8;
#endif
vStream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
vStream->codec->time_base = (AVRational) {1, 30};
vStream->codec->width = 640;
vStream->codec->height = 480;
vStream->codec->pix_fmt = PIX_FMT_YUV420P;
EDIT: I ran your program in Valgrind and it segfaults on av_write_frame. Looks like its time_base and other specs for output are not set properly.
Add the specs before avformat_write_header(), before it is too late.

read a text file into a binary tree but get run time error

I'm having run time error in addStu function when trying to read data from input file to binary tree, is there anything wrong with the format or pointer usage?
This is my code for reading file:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "BST_ADT.h"
// Structure
typedef struct
{
char* name;
char* market;
char* initial;
float stock;
}STUDENT;
// Prototype Delarations
void addStu (BST_TREE* list);
//void deleteStu (BST_TREE* list);
//void findStu (BST_TREE* list);
//void printList (BST_TREE* list);
//int compareStu (void* stu1, void* stu2);
//void processStu (void* dataPtr);
int main (void)
{
// Local Definitions
BST_TREE* list;
// Statements
list = BST_Create(compareStu);
addStu(list);
deleteStu(list);
findStu (list);
printList(list);
return 0;
}
/*===================== addStu =========================*/
void addStu (BST_TREE* list)
{
// Local Declarations
STUDENT* stuPtr;
FILE* fp;
char fileName[25];
char buffer [100];
// Statements
stuPtr = (STUDENT*)malloc (sizeof (STUDENT));
printf("Enter the file name: ");
gets(fileName);
fp = fopen(fileName, "r");
if(fp == NULL)
{
printf("Error cannot open the file!\n");
exit(101);
}
while(fgets(buffer, 100, fp) != NULL)
{
if (!stuPtr)
printf("MEmory overflow!\n"), exit(101);
sscanf(buffer, "%s %s %s %f", stuPtr->name, stuPtr->market, stuPtr->initial, &(stuPtr->stock));;
} // end while
BST_Insert(list, stuPtr);
} //addStu
this is my input:
Microsoft Corporation; NASDAQ MSFT 259.94B
Yahoo! Inc.; NASDAQ YHOO 37.67B
Baidu.com, Inc. (ADR); NASDAQ BIDU 8.64B
CNET Networks, Inc.; NASDAQ CNET 1.13B
QuickLogic Corporation; NASDAQ QUIK 88.62M
Answers Corporation; NASDAQ ANSW 53.49M
Apple Inc.; NASDAQ AAPL 114.17B
EarthLink, Inc.; NASDAQ ELNK 890.68M
Amazon.com, Inc.; NASDAQ AMZN 28.28B
IAC/InterActiveCorp; NASDAQ IACI 6.09B
Time Warner Inc.; NYSE TWX 57.29B
You havent initialize the strings in your structure. Bear in mind that char* name is a POINTER to a string, NOT the string itself. Same with the other strings. In a 32 bit app, the size of char* is actually 4 bytes. That means your entire structure is 16 bytes (3 * 4 byte pointers + 1 4 byte float).
You will need to allocate space for your strings and assign them to your structure before you can try populating them from the file data. Otherwise your structure will be pointing to whatever garbage was on the heap at the pointer name* as the address of your string.
EDIT:
Try allocating some space for your strings:
stuPtr->name = (char*) malloc(128 * sizeof(char));
This will create a string large enough to hold 127 chars. Do the same for your other strings.
A very, very long time since I've used used C, but the fact that you are not allocating space for STUDENT elements shouts out.
When you declare
// Structure
typedef struct
{
char* name;
char* market;
char* initial;
float stock;
}STUDENT;
You are declaring space for 16 bytes (assuming 4 byte pointers and floats).
Now each of the pointers name, market and initial have undefined values when created as a STUDENT. They point to random space - if you VERY lucky they are initialised to nulls.
A better definition for STUDENT would be
typedef struct
{
char name[MAX_NAME_SIZE];
char market[MAX_MARKET_SIZE];
char initial[MAX_INITIAL_SIZE];
float stock;
}STUDENT;
Where the MAXs are defines to be added earlier.
The other alternative would be to assign space just after creation
stuPtr = (STUDENT*)malloc (sizeof (STUDENT));
stuPtr->name = (char *)malloc(MAX_NAME_SIZE);
stuPtr->market = (char *)malloc(MAX_MARKET_SIZE);
stuPtr->initial = (char *)malloc(MAX_INITIAL_SIZE);
Array names are pointers to the first element of an array, so name and &name[0] are the same.
Hope this helps.
Andrew

Z_BUF_ERROR -5 while trying to decompress zlib data

I am trying to decompress some zlib data using the dataByDecompressingData: method from ObjectiveZlib example code, which I have had some help converting to be used with Objective-c instead of c++. Code below
- (NSData*) dataByDecompressingData:(NSData*)data{
Byte* bytes = (Byte*)[data bytes];
NSInteger len = [data length];
NSMutableData *decompressedData = [[NSMutableData alloc] initWithCapacity:COMPRESSION_BLOCK];
Byte* decompressedBytes = (Byte*) malloc(COMPRESSION_BLOCK);
z_stream stream;
int err;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
stream.next_in = bytes;
err = inflateInit(&stream);
CHECK_ERR(err, #"inflateInit");
while (true) {
stream.avail_in = len - stream.total_in;
stream.next_out = decompressedBytes;
stream.avail_out = COMPRESSION_BLOCK;
err = inflate(&stream, Z_NO_FLUSH);
[decompressedData appendBytes:decompressedBytes length:(stream.total_out-[decompressedData length])];
if(err == Z_STREAM_END)
break;
CHECK_ERR(err, #"inflate");
}
err = inflateEnd(&stream);
CHECK_ERR(err, #"inflateEnd");
free(decompressedBytes);
return decompressedData;
}
Once this runs I then get the Z_BUF_ERROR, I have read here which I know is referring to ASIHTTPReqest but I figure might be using the same zlib classes supplied by xcode to decompress, and they said its an error with the size of the Buffer not being able to handle the decompression of the file due to space.
I am not totally sure if this is correct, they offered two solutions to fix, the first would be to split the packet... thats not an option imo, the other thing to do would be to increase the buffer size.. I was wondering A, how could I do this? B, is there a better third option?
any help would be greatly appreciated.
Please refer to http://www.zlib.net/zlib_how.html
Z_BUF_ERROR will be explained further below, but suffice it to say that this is simply an indication that inflate() could not consume more input or produce more output. inflate() can be called again with more output space or more available input, which it will be in this code.
Some of the errors I see:
1/ everytime you set stream.next_in, you should set stream.avail_in, too. Note that you shouldn't change stream.avail_in when you are not giving next chunk of input. Setting the initial avail_in before calling inflateInit might be a good idea.
2/ Using inflateInit2(&stream, -MAX_WBITS) might be a good idea. Note that the normal version of inflateInit doesn't check data for compression type (gzip or zlib) and if it chooses gzip, your decompression will fail.
(should work, written without testing)
-(NSData*)decompressData:(NSData*)compressedData {
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
//we set the input, no need to change the values later
stream.next_in = (Bytef *) [compressedData bytes];
stream.avail_in = compressedData.length;
int result = inflateInit2(&stream, -MAX_WBITS);
if (result != Z_OK) {
return nil;
}
NSMutableData* uncompressedData = [NSMutableData data];
//make buffer big enough - 128KB
int bufferLength = 128 * 1024;
char *buffer = malloc(bufferLength);
while (true) {
stream.next_out = buffer;
stream.avail_out = bufferLength;
//calling with Z_FINISH because we already have all the input
result = inflate(&stream, Z_FINISH);
if (result != Z_OK && result != Z_STREAM_END) {
inflateEnd(&stream);
free(buffer);
return nil;
}
[uncompressedData appendBytes:buffer length:(bufferLength - stream.avail_out)];
if (result == Z_STREAM_END) {
break;
}
}
inflateEnd(&stream);
free(buffer);
return uncompressedData;
}

Why _vsnprintf crash at windows

When will the _vsnprintf crash?
I use it like this:
void My_Printf(const char *szFormatString, ...)
{
va_list my_args;
va_start(my_args, szFormatString);
AppendToLog(szFormatString, my_args);
va_end(my_args);
}
static void AppendToLog(const char *szFormatString, va_list argptr)
{
char szLine[MAX_LENGTH_STRING] = {0};
if ((NULL != szFormatString) && (0 != strcmp(szFormatString, ""))) {
if (strlen(szFormatString) > MAX_LENGTH_STRING) {
return;
}
#ifdef WIN32
_vsnprintf(szLine, MAX_LENGTH_STRING-1, szFormatString, argptr);
#endif
...
}
and the VC show that it was broken at:
_VALIDATE_RETURN( (ch != _T('\0')), EINVAL, -1); (output.c)
I don't know why.
According to MSND, it should return a value whether it was ok or not.
This is canonical code for using vsnprintf:
void Format( const char * fmt, ... ) {
const int BUFSIZE = 1024;
char buffer[BUFSIZE];
va_list valist;
va_start( valist, fmt );
vsnprintf( &buf[0], BUFSIZE, fmt, valist );
va_end( valist );
// do something with buffer
}
I don't know if this helps, but keep in mind that vsnprintf (and _vsnprintf I guess since Microsoft says they're identical) return different values on Windows and Unix. The Windows version returns -1 if you overflow the buffer, while the Unix version returns how many characters would have been written had the buffer been large enough. Here's a couple of links that I found helpful in this regard:
http://msdn.microsoft.com/en-us/library/1kt27hek(v=vs.80).aspx
http://bytes.com/topic/c/answers/590845-snprintf-return-value
EDIT: And here's an alternate version I found to get around this problem:
http://article.gmane.org/gmane.comp.version-control.git/75280/