In my file includes two columns and I'm try to gather data from file. I need to compare two value in one column. For example, if array[5] is higher than array[4], do something. Here my code:
int control(double col2[], double col3[], int subscript){
double a, b, fcontrol ;
int k /* group */ ;
/* some necessary values for JD controlling */
a = col2[subscript] ;
b = col2[subscript-1] ;
/* for JD controlling */
fcontrol = a - b ;
printf("kontrol = %.12f a = %.12f b = %.12f\n", fcontrol, a, b) ;
/* if value of between two data is equal or higher than 10 hour return 1 */
if(fcontrol >= 0.416666666667){
return 1 ;
}
else{
return 0 ;
}
b is always 0. How can I fix it?
My terminal is :
kontrol = 258.426728989849 a = 258.426728989849 b = 0.000000000000
kontrol = 258.447161800788 a = 258.447161800788 b = 0.000000000000
kontrol = 258.467594711488 a = 258.467594711488 b = 0.000000000000
kontrol = 260.245248070103 a = 260.245248070103 b = 0.000000000000
kontrol = 260.265680861012 a = 260.265680861012 b = 0.000000000000
kontrol = 260.286113551461 a = 260.286113551461 b = 0.000000000000
kontrol = 260.306546441912 a = 260.306546441912 b = 0.000000000000
Here my all code :
/* TASK */
#include<stdio.h>
int kontrol(double col2[], double col3[], int subscript) ;
int main(){
int kolon1,
n = 0, /* for array */
j, z, /* for "for" loopr */
flag = 0 ;
int grup = 0 ;
double kolon2, kolon3,
col2[100000], col3[100000] ;
char ignore[100];
FILE *okuPtr ;
FILE *yazPtr ;
char oku_tbl[100] ;
sprintf(oku_tbl, "deneme.tbl") ;
/* error if file isnt opened*/
if ((okuPtr = fopen(oku_tbl, "r")) == NULL)
printf("%s Acilamadi", oku_tbl) ;
/* file is opened */
else{
char yaz_tbl[100] ;
sprintf(yaz_tbl, "deneme_data.tbl") ;
/* errof if file isnt opened */
if((yazPtr = fopen(yaz_tbl, "w")) == NULL)
printf("%s acilamadi\n", yaz_tbl) ;
/* file is opened */
else{
/* first read */
fscanf(okuPtr, "%d%lf%lf", &kolon1, &kolon2, &kolon3) ;
/* until end of file */
while (!feof(okuPtr)){
/* ignore first 3 line */
fgets(ignore, 100, okuPtr) ;
col2[n] = kolon2 ;
col3[n] = kolon3 ;
flag = control(col2, col3, n) ;
n++ ;
/* if flag == 1 */
if (flag == 1){
for (z = 0 ; z <= --n ; z++){
fprintf(yazPtr, "%d\t%.12f\t%.12f\n", grup, col2[z], col3[z]) ;
}
n = 0 ;
grup++ ;
}
/* yeni veri oku */
fscanf(okuPtr, "%d%lf%lf", &kolon1, &kolon2, &kolon3) ;
}
/* diziyi yazdir
for (j = 0 ; j <= n-1 ; j++){
printf("%d\t%-.12f\t%-.12f\n", k, col2[j], col3[j]) ;
} */
}
}
return 0 ;
}
int control(double col2[], double col3[], int subscript){
double a, b,
fcontrol ;
int k /* group */ ;
/* some necessary values for JD controlling */
a = col2[subscript] ;
b = col2[subscript-1] ;
/* for JD controlling */
fcontrol = a - b ;
printf("kontrol = %.12f a = %.12f b = %.12f\n", fcontrol, a, b) ;
/* if value of between two data is equal or higher than 10 hour return 1 */
if(fcontrol >= 0.416666666667){
return 1 ;
}
else{
return 0 ;
}
}
Problem is that when you call control for first time when n=0
flag = control(col2,col3, n);
But notice here b=col2[subscript-1] will actually be b=col2[-1] which is creating problem as array indexing start with 0 thus your program has this behaviour .
while (!feof(okuPtr))
It is always wrong. See here-Why is “while ( !feof (file) )” always wrong?
Instead use this -
while(fgets(ignore, 100, okuPtr))
{
/*Your code*/
}
Related
I have found a great example of handling Python-style INDENT/OUTDENT in Flex here: http://matt.might.net/articles/standalone-lexers-with-lex/
The code is:
%{
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#define MAX_DEPTH 72
int nesting = 0 ;
unsigned int indent_stack[MAX_DEPTH] ;
unsigned int level = 0 ;
unsigned int first = 1 ;
void process_indent(char* line) ;
%}
PUNCT [-+*/=<>:]*
ID [A-Za-z_][A-Za-z0-9_]*
INT [0-9]+
%option noyywrap
%%
^[ ]*\n {/* Ignore blank lines. */}
^[ ]*[^ \n]+ {int last = yyleng - 1;
process_indent(yytext) ;
while ((last >= 0) &&
(yytext[last] != ' ')) {
unput(yytext[last]);
last-- ;}}
"(" {printf(" "); ECHO; nesting++ ; }
")" {printf(" "); ECHO; nesting-- ; }
{ID}|{INT}|{PUNCT} {printf(" ") ; ECHO;}
[ \r] {}
\n {}
<<EOF>> { process_indent("") ; return 0 ; }
%%
unsigned int white_count(char* line) {
unsigned int count = 0 ;
while (*line == ' ')
count++, line++ ;
return count ;
}
void process_indent(char* line) {
if (nesting)
/* Ignore indents while nested. */
return ;
unsigned int indent = white_count(line) ;
if (indent == indent_stack[level]) {
if (!first) printf(" ;") ; // EMIT END_STATEMENT
first = 0 ;
return ;
}
if (indent > indent_stack[level]) {
printf(" {") ; // EMIT BLOCK_START
assert(level+1 < MAX_DEPTH) ;
indent_stack[++level] = indent ;
return ;
}
while (indent < indent_stack[level]) {
--level ;
printf(" }") ; // EMIT BLOCK_END
}
assert(level >= 0) ;
}
int main(int argc, char* argv[]) {
indent_stack[0] = 0 ;
yylex() ;
printf("\n") ;
}
Basically, it converts code like this:
def f(x):
y = x * x
e = (m * c
* c)
if x > 0:
return e
else:
return y
To this:
def f ( x ) : { y = x * x ; e = ( m * c * c ) ;
if x > 0 : { return e } else : { return y } }
Which is exactly what I need. With one difference: I want the lexer to return the appropriate tokens instead of printing out the curly braces.
The problem is with the OUTDENTs. This happens in a while block in the process_indent function (meaning: there may be more than one block to "close"). And that means I would have to return more than one tokens at the same time - which is NOT possible with Lex/Flex.
Any ideas how I could change that to make it work? Are there any working examples with what I need?
Any ideas how I could change that to make it work? Are there any
working examples with what I need?
You could base your code on the Python lexer example included with RE/flex, see ptokens.l. This lexer fully supports Python's syntax rules such as indentation blocks, and implicit and explicit line joining which isn't possible with process_indent(). Multiple "OUTDENT" (RE/flex "dedent") are generated when multiple blocks close.
The example requires RE/flex as a more advanced version of Flex. But RE/flex is very much like Flex and accepts Flex specifications, so moving on to RE/flex should be easy.
[This question has been solved]
(This question has already been posted on the Matlab forum, here : http://www.mathworks.com/matlabcentral/answers/223415-mex-compiled-function-used-to-compute-set-intersection-and-difference-keeps-crashing)
Hi Guys,
I'm trying to build a very simple function that is supposed to computed the "intersection" and "difference" of two sets, returning the corresponding indices.
For instance, if we have
in1 = [1 2 4 5 9]
in2 = [2 3 4 8]
it should return
common1 = [2 3] % since all(in1(common1) == in2(common2))
common2 = [1 3]
only1 = [1 4 5] % the remaining indices, not in common1
only2 = [2 4] % the ones not in common2
I could do that using intersect and setdiff, but because I have small sets and since I call this function thousands of times, I think doing it using a compiled C-mex file should be the fastest way. It really is the bottleneck of my algorithm at the moment.
I coded this function
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
mexPrintf("Starting ...\n") ;
/* Check nbr of inputs and outputs */
if (nrhs != 2 || nlhs != 4)
mexErrMsgTxt("intersectFast needs 4 outputs and 2 inputs") ;
const mxArray* pin1 = prhs[0] ;
const mxArray* pin2 = prhs[1] ;
/* Inputs should be column vectors */
if (mxGetN(pin1) != 1 || mxGetN(pin2) != 1)
mexErrMsgTxt("inputs arguments should be column vectors") ;
mwSize dims1 = mxGetM(pin1) ;
mwSize dims2 = mxGetM(pin2) ;
double* in1 = mxGetPr(pin1) ;
double* in2 = mxGetPr(pin2) ;
mexPrintf("Checks passed\n") ;
mwIndex* idCommon1 = mxCalloc(dims1, sizeof(mwIndex)) ; // At most dims1 elements
mwIndex* idCommon2 = mxCalloc(dims2, sizeof(mwIndex)) ; /* AT MOST dims2 and NOT dims1 ... this was the error. Damn I feel so stupid right now. */
mwIndex* idOnly1 = mxCalloc(dims1, sizeof(mwIndex)) ; /* Same error here */
mwIndex* idOnly2 = mxCalloc(dims2, sizeof(mwIndex)) ;
mwSize sizeCommon1, sizeCommon2, sizeOnly1, sizeOnly2 ;
mwIndex i, j ;
mwIndex k, l ;
int match ;
/* Intersect fast */
/* in1 */
k = 0 ; l = 0 ;
for(i = 0 ; i < dims1 ; i++) {
match = 0 ;
for(j = 0 ; j < dims2 ; j++) {
if (in1[i] == in2[j]) {
idCommon1[k++] = (i+1) ; /* Matlab <-> C convention */
match = 1 ;
break ;
}
}
if (! match) {
idOnly1[l++] = (i+1) ;
}
}
sizeCommon1 = k ;
sizeOnly1 = l ;
/* in2 */
k = 0 ; l = 0 ;
for(i = 0 ; i < dims2 ; i++) {
match = 0 ;
for(j = 0 ; j < dims1 ; j++) {
if (in2[i] == in1[j]) {
idCommon2[k++] = (i+1) ;
match = 1 ;
break ;
}
}
if (! match)
idOnly2[l++] = (i+1) ;
}
sizeCommon2 = k ;
sizeOnly2 = l ;
/* Return results */
mexPrintf("Sizes = %d, %d, %d, %d\n", sizeCommon1, sizeCommon2, sizeOnly1, sizeOnly2) ;
plhs[0] = mxCreateNumericMatrix(sizeCommon1, 1, mxUINT32_CLASS, mxREAL);
plhs[1] = mxCreateNumericMatrix(sizeCommon2, 1, mxUINT32_CLASS, mxREAL);
plhs[2] = mxCreateNumericMatrix(sizeOnly1, 1, mxUINT32_CLASS, mxREAL);
plhs[3] = mxCreateNumericMatrix(sizeOnly2, 1, mxUINT32_CLASS, mxREAL);
if (plhs[0] == NULL || plhs[1] == NULL || plhs[2] == NULL || plhs[3] == NULL)
mexErrMsgTxt("Could not create mxArray.\n");
mxSetData(plhs[0], idCommon1);
mxSetData(plhs[1], idCommon2);
mxSetData(plhs[2], idOnly1);
mxSetData(plhs[3], idOnly2);
mexPrintf("Done.\n") ;
}
When I test it, it often works, but it always eventually crashes ... For instance, using
% Test intersect fast
clc ; close all ; clear all ;
while true
clc ;
id1 = unique(randi(10, 8, 1)) ;
id2 = unique(randi(12, 6, 1)) ;
[idCommon1, idCommon2, idOnly1, idOnly2] = intersectFast(id1, id2) ;
pause(0.1)
end
it always crashes at some point, after the mex function is done. What I mean is that I get an error like "Matlab has encountered an internal problem and needs to close". So I guess there is some problem with either the mxCreateNumericMatrix or the mxSetData, but I can't figure out what is the problem exactly. I tried changing the index types (uint32, uint64, int, ...) but it did not really change anything.
I am using R2015a on OSX 10.10.3 and the compiled is the default one (Clang).
Thanks a lot for your help !
=================
EDIT : let me be more specific about how it crashes.
Sometimes, MATLAB just start to freeze (and I get the rotating colored mouse pointer ...), and eventually crashes. I need to force MATLAB to quit in this case.
Some other times, I get an error message from MATLAB, saying it encountered an internal error and needs to quit. In this case I can find a Matlab crash file. I uploaded one crash report here : http://pastebin.com/ry7MN7yw
It would be better if you can supply the error message from OS X, which can be obtained by clicking the Crashed notification on the upper-right corner of the screen. For questions involving some low-level (compared to Matlab itself) stuffs like C, the crash report from the Operating System is often useful, since you can see what crashed the program. You can paste it in full to a pastebin or whatever.
If you really find that it crashed inside your code, add the -g flag to clang so you can get some line number in the crash report.
Sorry for not writing this as a comment — I don't have 50 rep yet.
In the code bellow, each work items generate a array sum_qcos_i.
In order to add them I first make local addition using the local array sum_qcos_tmp.
Then I copy every local array in a global one dimensional matrix sum_qcos_part.
I need to add that matrix columns for my purpose, that's what does each work item before using the result.
Here is the code
__kernel __attribute__((vec_type_hint(double4))) void energy_forces( const int atom_number,
const int nvect,
__global double4 *kvect,__global double *qcos,__global double *qsin,
__global double *cst_ewald ,
__global double4 *positions,
__global double4 *forces_r,
__global double *sum_qcos_part,__global double *sum_qsin_part)
{
int i = 0 ;
int gti = 0 , ggi = 0 , lti = 0;
double kr = (double)0.0 ;
double ss = (double)0.0 , cc = (double)0.0 ;
double prod = (double)0.0 ;
double valqcos = 0. , valqsin = 0. ;
double4 zeroes_4 = (double4){ 0.0,0.0,0.0,0.0 };
double sum_qcos_i[NVECTOR_MAX] ;
double sum_qsin_i[NVECTOR_MAX] ;
#if defined NVECTOR_MAX
__local double sum_qcos_tmp[NVECTOR_MAX] ;
__local double sum_qsin_tmp[NVECTOR_MAX] ;
#endif
lti = get_local_id(0);
ggi = get_group_id(0);
for (k=0;k<nvect;k++) { /*k-vectors*/
sum_qcos_tmp[k] = .0 ;
sum_qsin_tmp[k] = .0 ;
sum_qcos_i[k] = .0 ;
sum_qsin_i[k] = .0 ;
}
double fk = (double)0.0 ;
double4 fr_i = zeroes_4 ;
double4 kvec_i = zeroes_4;
for (gti = get_global_id(0); gti < atom_number; gti += get_global_size(0))
{
pos_i = positions[gti];
for (k=0;k<nvect;k++) { /* sum over k-vectors to compute QCOS and QSIN for Ewald sum*/
prod = dot((double4)pos_i,(double4)kvect[k]);
ss = (double)sincos(-prod,&cc);
valqcos = cc ;
valqsin = ss ;
// valqcos = 1. ;
// valqsin = 1. ;
qcos[gti*NVECTOR_MAX+k] = valqcos ;
qsin[gti*NVECTOR_MAX+k] = valqsin ;
sum_qcos_i[k] = valqcos ; /* private variable */
sum_qsin_i[k] = valqsin ;
} /* end sum over k-vectors to compute QCOS and QSIN for Ewald sum*/
} // end for gti
int ii = 0 ;
for ( ii = 0;ii<get_local_size(0);ii++ )
{
if (lti == ii)
{
for (k=0;k<nvect;k++)
{ /* k-vectors */
sum_qcos_tmp[k] += sum_qcos_i[k] ; /* accumulates private data to local variable */
sum_qsin_tmp[k] += sum_qsin_i[k] ;
}
barrier(CLK_LOCAL_MEM_FENCE|CLK_GLOBAL_MEM_FENCE) ;
}
}
if (lti == 0)
{
for (k=0;k<nvect;k++) {
sum_qcos_part[ggi*NVECTOR_MAX+k] = sum_qcos_tmp[k] ; /* cp local data to global array */
sum_qsin_part[ggi*NVECTOR_MAX+k] = sum_qsin_tmp[k] ;
}
}
int iii = 0 ;
for (gti = get_global_id(0); gti < atom_number; gti += get_global_size(0))
{
fr_i = zeroes_4 ;
barrier(CLK_LOCAL_MEM_FENCE|CLK_GLOBAL_MEM_FENCE) ;
for (k=0;k<nvect;k++)
{
sum_qcos_i[k] = .0 ;
sum_qsin_i[k] = .0 ;
for (iii=0;iii<get_num_groups(0);iii++)
{
sum_qcos_i[k] += sum_qcos_part[iii*NVECTOR_MAX+k] ;
sum_qsin_i[k] += sum_qsin_part[iii*NVECTOR_MAX+k] ;
}
}
barrier(CLK_LOCAL_MEM_FENCE|CLK_GLOBAL_MEM_FENCE) ;
for (k=0;k<nvect;k++)
{
fk = ( sum_qcos_i[k]*qsin[gti*NVECTOR_MAX+k] - sum_qsin_i[k]*qcos[gti*NVECTOR_MAX+k] ) ;
fr_i += cst_ewald[k] * fk * kvect[k] ;
}
#if defined(SCALAR_KERNELS)
forces_r[gti].x = fr_i.x;
forces_r[gti].y = fr_i.y;
forces_r[gti].z = fr_i.z;
forces_r[gti].w = .0 ;
#elif defined(VECTOR_KERNELS)
forces_r[gti] = fr_i;
#endif
} // end for gti
}
This kernel doesn't work and I can't figure why.
Some hints would be very helpful here.
Thank you.
Adding a barrier made the trick:
for ( ii = 0;ii<get_local_size(0);ii++ )
{
if (lti == ii)
{
barrier(CLK_LOCAL_MEM_FENCE|CLK_GLOBAL_MEM_FENCE) ;
for (k=0;k<nvect;k++)
{ /* k-vectors */
sum_qcos_tmp[k] += sum_qcos_i[k] ; /* accumulates private data to local variable */
sum_qsin_tmp[k] += sum_qsin_i[k] ;
}
}
}
The final of the the vector forces_r is still wrong abut it's always the same now.
Actually the problem is not solved.
I define the global work size based on the number of particles so that each work item takes care of one particles.
In my calculations, I dot product each particles coordinates with a certain number of vectors.
My issue now is that the result of those dot products depends on the group size. I put the vectors in a array of double4. The global work size goes from something like 1000 to 10000, whereas the number of vectors I use for the dot product is always around 200.
I'm wondering whether there is a requirement on arrays size regarding the global work size.
for (gti = get_global_id(0); gti < atom_number; gti += get_global_size(0))
{
pos_i = positions[gti];
for (k=0;k<nvect;k++) { /* sum over k-vectors to compute QCOS and QSIN for Ewald sum*/
prod = dot((double4)pos_i,(double4)kvect[k]);
ss = (double)sincos(-prod,&cc);
valqcos = cc ;
valqsin = ss ;
qcos[gti*NVECTOR_MAX+k] = valqcos ;
qsin[gti*NVECTOR_MAX+k] = valqsin ;
sum_qcos_i[k] = valqcos ; /* private variable */
sum_qsin_i[k] = valqsin ;
} /* end sum over k-vectors to compute QCOS and QSIN for Ewald sum*/
} // end for gtiforgot
Any hints here?
I am new to C and at the moment I am trying to debug my code. I am hitting a dead end on this particular error. It gives me an error :
THREAD 1: EXC_BAD_ACCESS(code=2, address = 0x7fff5fc00000)
The error appears at the section krec[0].
I am still yet to figure out what is allow in C and what is not allow when writing c. Would love to have some suggestion to make my code more efficient too. Here is my code :
int k_vector_calculation(int krec[3])
{
int Boxx[3], Boxy[3], Boxz [3];
Boxx[0] = lx ;
Boxx[1] = 0 ;
Boxx[2] = 0 ;
Boxy[0] = 0 ;
Boxy[1] = ly ;
Boxy[2] = 0 ;
Boxz[0] = 0 ;
Boxz[1] = 0 ;
Boxz[2] = lz ;
int Productbc[3], Productac[3], Productab[3] ;
Productbc[0] = Boxy[1] * Boxz[2] ;
Productbc[1] = 0 ;
Productbc[2] = 0 ;
Productac[0] = 0 ;
Productac[1] = Boxx [0]* Boxz [2] ;
Productac[2] = 0 ;
Productab[0] = 0 ;
Productab[1] = 0 ;
Productab[2] = Boxx [0]* Boxy [1] ;
float V0 = 0;
V0 = lx*ly*lz ;
int u[3], v[3], w[3] ;
u[0] = 2*PI/V0*Productbc[0] ;
u[1] = 2*PI/V0*Productbc[1] ;
u[2] = 2*PI/V0*Productbc[2] ;
v[0] = 2*PI/V0*Productac[0] ;
v[1] = 2*PI/V0*Productac[1] ;
v[2] = 2*PI/V0*Productac[2] ;
w[0] = 2*PI/V0*Productab[0] ;
w[1] = 2*PI/V0*Productab[1] ;
w[2] = 2*PI/V0*Productab[2] ;
int l, m, o;
l = nearbyint(lx) ;
m = nearbyint(ly) ;
o = nearbyint(lz) ;
krec[0] = l*u[0]+m*v[0]+o*w[0] ;
krec[1] = l*u[1]+m*v[1]+o*w[1] ;
krec[2] = l*u[2]+m*v[2]+o*w[2] ;
return k_vector_calculation(&krec[3]);
}
The problem is here
return k_vector_calculation(&krec[3]);
You have passed an int array krek[3] in which the valid locations are krek[0],krek[1] and krek[2].Also,you have an infinite recursion as you call the function again and again in the last return statement.
I have been supplied a CSV line parser to use in a program, and it seems to have a bug where if there is a blank line at the end of the text file it prints out an empty line, like so
My input is this
test, does, this, work
1, second, line, same
My output looks like this. Not only does it cut off the last word, but it prints out the empty line.
test = 1
does = second
this = line
work = same
test =
What it's supposed to do is match every word with the coinciding one in the top line, which it does, but I don't know where the last "test = " is coming from. Here's the code I was supplied, any ideas about what's wrong with it would be a huge help. Thanks.
/*
* Just an array of characters representing a single filed.
*/
typedef char f_string[MAX_CHARS+1] ; /* string for each field */
/*
* A parsed CSV line, with the number of fields and upto MAX_FIELDS themselves.
*/
typedef struct {
int nfields ; /* 0 => end of file */
f_string field[MAX_FIELDS] ; /* array of strings for fields */
} csv_line ;
/*
* Returns true iff the character 'ch' ends a field. That is, ch is end of file,
* a comma, or a newline.
*/
bool is_end_of_field(char ch) {
return (ch == ',') || (ch == '\n') || (ch == EOF) ;
}
/*
* Return the minimum of two integers.
*/
int min(int x, int y) {
return x < y ? x : y ;
}
/*
* Read the next field from standard input. Returns the value of getchar() that
* stopped (terminated) the field.
*/
int get_field(f_string field) {
/**BEGIN_SOLN**/
int i ;
int next_char ;
next_char = getchar() ;
for ( i = 0 ; ! is_end_of_field(next_char) ; ++i ) {
field[i] = next_char ;
next_char = getchar() ;
}
field[i] = '\0' ;
return next_char ;
/**END_SOLN**/
}
/*
* Read in a CSV line. No error checking is done on the number of fields or
* the size of any one field.
* On return, the fields have been filled in (and properly NUL-terminated), and
* nfields is the count of the number of valid fields.
* nfields == 0 means end of file was encountered.
*/
csv_line get_line() {
/**BEGIN_SOLN**/
csv_line line ;
int fi = 0 ; /* index of current field in line */
int stop_ch ; /* character that terminated the last field */
stop_ch = get_field(line.field[fi++]) ;
while ( stop_ch == ',' ) {
stop_ch = get_field(line.field[fi++]) ;
}
line.nfields = (stop_ch == EOF) ? 0 : fi ;
return line ;
/**END_SOLN**/
}
/*
* Print a CSV line, associating the header fields with the
* data line fields.
* The minimum of the number of fields in the header and the data
* determines how many fields are printed.
*/
void print_csv(csv_line header, csv_line data) {
/**BEGIN_SOLN**/
int i ;
int nfields = min(header.nfields, data.nfields) ;
for ( i = 0 ; i < nfields ; ++i ) {
printf("%s = %s\n", header.field[i], data.field[i]) ;
}
/**END_SOLN**/
}
/*
* Driver - read a CSV line for the header then read and print data lines
* until end of file.
*/
int main() {
csv_line header ;
csv_line current ;
header = get_line() ;
current = get_line() ;
while ( current.nfields > 0 ) {
print_csv(header, current) ;
current = get_line() ;
}
return 0 ;
}
bool is_end_of_field(int ch) {
return (ch == ',') || (ch == '\n') || (ch == EOF) ;
}
bool get_field(f_string field){
int i ;
int next_char ;
for ( i = 0 ; ! is_end_of_field(next_char=getchar()) ; ++i ) {
field[i] = next_char ;
}
field[i] = '\0';
return (next_char == ',')? true : false;
}
csv_line get_line() {
csv_line line ;
int fi = 0;
while(get_field(line.field[fi++]))
;
line.nfields = line.field[fi-1][0] ? fi : 0;
return line ;
}