Array Conversions in C, or Changing Data Format

closed account (4jNqM4Gy)
I've been looking for a few days all over the internet and I just can't get clarity on this at all:

The idea:
I am given a set of data with a column on the leftmost part of my data as a designator. This column distinguishes what set of data goes with what, but the format is awkward to handle, programming-wise:

0006 3129675 391894 14.31 2589014 94.57 148767 5.43 2635952 96.28 2589016 94.57
00061 3 0 0.00 3 100.00 0 0.00 3 100.00 3 100.00
00062 1 0 0.00 1 100.00 0 0.00 1 100.00 1 100.00
00063 1 0 0.00 0 0.00 1 100.00 0 0.00 0 0.00
0007 2230275 296987 15.36 1786722 92.42 146566 7.58 1842030 95.28 1786722 92.42
1100 2234323 11137 0.50 2085441 93.80 137745 6.20 2127517 95.70 2085441 93.80
1101 118662 214 0.18 115408 97.43 3040 2.57 115973 97.91 115408 97.43
11011 2212 2 0.09 2157 97.60 53 2.40 2167 98.05 2157 97.60
1102 62665 143 0.23 60929 97.45 1593 2.55 61210 97.90 60929 97.45
11021 895 4 0.45 862 96.75 29 3.25 864 96.97 862 96.75
1103 19478 37 0.19 18980 97.63 461 2.37 19073 98.11 18980 97.63
11031 265 1 0.38 258 97.73 6 2.27 259 98.11 258 97.73
1104 73202 108 0.15 71129 97.31 1965 2.69 71488 97.80 71129 97.31
11041 1396 3 0.22 1340 96.20 53 3.80 1355 97.27 1340 96.20

(Sorry for the formatting) So, the "0006" has a subgroup of 3 more lines of data: 00061, 00062, 00063. The rest of the data to the right of this column I process and know what to do. I just have this stumbling block on how to make this column into what I want.

The question:
Initially, I scanf in all of that in their respective columns (12 columns total) having the first column, in particular, as int. What I want to do with this column is chop off any 5th digit, which - from all of the reading I've done over the last few days - needs to be in character format. Well, I'm not sure how to convert an int array into a character array, truncate, and then convert back to int. How do I do this or is there a far more efficient way to go about this?

What I want to see:
0006 3129675 391894 14.31 2589014 94.57 148767 5.43 2635952 96.28 2589016 94.57
0006 3 0 0.00 3 100.00 0 0.00 3 100.00 3 100.00
0006 1 0 0.00 1 100.00 0 0.00 1 100.00 1 100.00
0006 1 0 0.00 0 0.00 1 100.00 0 0.00 0 0.00
0007 2230275 296987 15.36 1786722 92.42 146566 7.58 1842030 95.28 1786722 92.42
1100 2234323 11137 0.50 2085441 93.80 137745 6.20 2127517 95.70 2085441 93.80
1101 118662 214 0.18 115408 97.43 3040 2.57 115973 97.91 115408 97.43
1101 2212 2 0.09 2157 97.60 53 2.40 2167 98.05 2157 97.60
1102 62665 143 0.23 60929 97.45 1593 2.55 61210 97.90 60929 97.45
1102 895 4 0.45 862 96.75 29 3.25 864 96.97 862 96.75
1103 19478 37 0.19 18980 97.63 461 2.37 19073 98.11 18980 97.63
1103 265 1 0.38 258 97.73 6 2.27 259 98.11 258 97.73
1104 73202 108 0.15 71129 97.31 1965 2.69 71488 97.80 71129 97.31
1104 1396 3 0.22 1340 96.20 53 3.80 1355 97.27 1340 96.20

That way, in my loops, all I have to do is check that first column to see if the previous entry is equal to the current. If so, process. If not, keep as is.

Desired end result:
0006 SUM INDIVIDUAL COLUMNS ...
0007 KEEP AS IS
1100 KEEP AS IS
1101 SUM INDIVIDUAL COLUMNS ...
1102 SUM INDIVIDUAL COLUMNS ...
....

I've never done something like this and really don't know how to code it. So, this is all I have as a starting point:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  //Processing values into arrays:
  FILE *fp;
  fp = fopen("test.txt", "r");
  
  //Numbers to be summed:
  l = (int*) malloc(N*sizeof(double));
  ti = (int*) malloc(N*sizeof(double));
  ef = (int*) malloc(N*sizeof(double));
  z4c = (int*) malloc(N*sizeof(double));
  z4b = (int*) malloc(N*sizeof(double));
  cc = (int*) malloc(N*sizeof(double));
  wc = (int*) malloc(N*sizeof(double));
  
  //Percentages to be recalculated:
  p1 = (double *) malloc(N*sizeof(double));
  p2 = (double *) malloc(N*sizeof(double));
  p3 = (double *) malloc(N*sizeof(double));
  p4 = (double *) malloc(N*sizeof(double));
  p5 = (double *) malloc(N*sizeof(double));
  
  //Creating arrays:
  for( i = 0; i < N + 1; i++)
  {
       fscanf(fp, "%d %d %d %lf %d %lf %d %lf %d %lf %d %lf", 
                  &list, &total_input, &edit_fail, &perc1, &zip_4_coded, &perc2,
                  &zip_4_blank, &perc3, &crc_coded, &perc4, &ws_coded, &perc5); //Reads the file that I showed you a sample of and takes in only what I currently need.
       l[i] = list;
       ti[i] = total_input;
       ef[i] = edit_fail;
       z4c[i] = zip_4_coded;
       z4b[i] = zip_4_blank;
       cc[i] = crc_coded;
       wc[i] = ws_coded;
       
       /*printf("%d %d %d %d %d %d %d\n", l[i], ti[i],
                   ef[i], z4c[i], z4b[i], cc[i], wc[i]);*/ //Checks to see if I'm getting what I'm suppose to have.
  }
  
  //Changing any list array values from 5-digit to 4:
  ?????????????...


Thanks...
Last edited on
closed account (4jNqM4Gy)
If someone could help me out, I would be grateful.
Instead scanning in the number as an integer, scan it in as a character array of size 5 (or more), then you convert each digit from the array to a single integer from indices 0 to 4.
As a template you can use the following code. I did not check that a line of the file can contain more than 11 columns. You should do such a check.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <map>
#include <array>

int main()
{
	// I used a string instead of the input file
	std::string s =
	"0006 3129675 391894 14.31 2589014 94.57 148767 5.43 2635952 96.28 2589016 94.57\n"
	"00061 3 0 0.00 3 100.00 0 0.00 3 100.00 3 100.00\n"
	"00062 1 0 0.00 1 100.00 0 0.00 1 100.00 1 100.00\n"
	"00063 1 0 0.00 0 0.00 1 100.00 0 0.00 0 0.00\n"
	"0007 2230275 296987 15.36 1786722 92.42 146566 7.58 1842030 95.28 1786722 92.42\n"
	"1100 2234323 11137 0.50 2085441 93.80 137745 6.20 2127517 95.70 2085441 93.80\n"
	"1101 118662 214 0.18 115408 97.43 3040 2.57 115973 97.91 115408 97.43\n"
	"11011 2212 2 0.09 2157 97.60 53 2.40 2167 98.05 2157 97.60\n"
	"1102 62665 143 0.23 60929 97.45 1593 2.55 61210 97.90 60929 97.45\n"
	"11021 895 4 0.45 862 96.75 29 3.25 864 96.97 862 96.75\n"
	"1103 19478 37 0.19 18980 97.63 461 2.37 19073 98.11 18980 97.63\n"
	"11031 265 1 0.38 258 97.73 6 2.27 259 98.11 258 97.73\n"
	"1104 73202 108 0.15 71129 97.31 1965 2.69 71488 97.80 71129 97.31\n"
	"11041 1396 3 0.22 1340 96.20 53 3.80 1355 97.27 1340 96.20\n";

	const size_t N = 11;
	std::map<std::string, std::array<double, N>> m;

	std::string line;

	std::istringstream outer_is( s );

	while ( std::getline( outer_is, line ) )
	{
		std::istringstream inner_is( line );
		std::string key;

		if ( !( inner_is >> key ) ) continue; 

		key.assign( key, 0, 4 );

		if ( m.find( key ) == m.end() )
		{
			m[key].fill( 0.0 );
			std::copy( std::istream_iterator<double>( inner_is ),
				   std::istream_iterator<double>(),
				   m[key].begin() );
		}
		else
		{
			std::transform( std::istream_iterator<double>( inner_is ),
			                std::istream_iterator<double>(),
					m[key].begin(),
					m[key].begin(),
					[]( double x, double y ) { return ( x + y ); } );
		}
	}

	//for each ( auto p in m ) MS VC++ 2010
	for ( auto p : m ) 
	{
		std::cout << p.first << '\t';
		//for each ( double x in p.second ) MS VC++ 2010
		for ( double x : p.second )
		{
			std::cout << std::fixed << std::setprecision( 2 ) << x << ' ';
		}
		std::cout << std::endl;
	}
	std::cout << std::endl;
}


The output is

0006    3129680.00 391894.00 14.31 2589018.00 294.57 148768.00 105.43 2635956.00
 296.28 2589020.00 294.57
0007    2230275.00 296987.00 15.36 1786722.00 92.42 146566.00 7.58 1842030.00 95
.28 1786722.00 92.42
1100    2234323.00 11137.00 0.50 2085441.00 93.80 137745.00 6.20 2127517.00 95.7
0 2085441.00 93.80
1101    120874.00 216.00 0.27 117565.00 195.03 3093.00 4.97 118140.00 195.96 117
565.00 195.03
1102    63560.00 147.00 0.68 61791.00 194.20 1622.00 5.80 62074.00 194.87 61791.
00 194.20
1103    19743.00 38.00 0.57 19238.00 195.36 467.00 4.64 19332.00 196.22 19238.00
 195.36
1104    74598.00 111.00 0.37 72469.00 193.51 2018.00 6.49 72843.00 195.07 72469.
00 193.51
Last edited on
closed account (4jNqM4Gy)
Hmm, the trouble is, for one, I'm not familiar with your code to know if it's exactly what I want since I do still have to recalculate the percentages. Too, you have hardwired the data into your code to process whereas I am reading from a file to process.

I have been working on a small project to learn something about character arrays. However, the results aren't what I'm looking for:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () 
{
  string line;
  ifstream myfile ("test2.txt");
  
  int i, N, counter = 0;
  int *n1, num1, *n2, num2;
  char *c, chara;
  
  //Check file length:  
  if (myfile.is_open())
  {
    while ( myfile.good() )
    {
      getline (myfile,line);
      cout << line << endl;
      N = counter++;
    }
    cout << N << endl;
  }
  
  else cout << "Unable to open file"; 

  myfile.close();

  //Processing values into arrays:
  FILE *fp;
  fp = fopen("test2.txt", "r");
  
  n1 = (int*) malloc(N*sizeof(int));
  n2 = (int*) malloc(N*sizeof(int));
  c = (char*) malloc(N*sizeof(char));
  
  for( i = 0; i < N + 1; i++)
  {
       fscanf(fp, "%c %d", &chara, &num2);
       c[i] = chara;
       //n1[i] = num1;
       n2[i] = num2;
       printf("%c %d\n", c[i], n2[i]);
  }
  
  /*for( i = 0; i < N + 1; i++)
  {
       c[i] = sprintf(chara, "%d", n1[i]);
       printf("c[%d] = %c\n", i, c[i]);
  }*/
  
  
  free (n1);
  free(n2);
  free(c);
  fclose(fp);
  

  return 0;
}


0006 342
00061 344
00062 4237
00063 34
0007 322
1100 1
1101 324
11011 2142
7
0 6
  342

 61
  344

 62
  4237

 63
  34


If I do it another way, then I get the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () 
{
  string line;
  ifstream myfile ("test2.txt");
  
  int i, N, counter = 0;
  int *n1, num1, *n2, num2;
  char *c, chara[5];
  
  //Check file length:  
  if (myfile.is_open())
  {
    while ( myfile.good() )
    {
      getline (myfile,line);
      cout << line << endl;
      N = counter++;
    }
    cout << N << endl;
  }
  
  else cout << "Unable to open file"; 

  myfile.close();

  //Processing values into arrays:
  FILE *fp;
  fp = fopen("test2.txt", "r");
  
  n1 = (int*) malloc(N*sizeof(int));
  n2 = (int*) malloc(N*sizeof(int));
  c = (char*) malloc(N*sizeof(char));
  
  for( i = 0; i < N + 1; i++)
  {
       fscanf(fp, "%d %d", &num1, &num2);
       //c[i] = chara;
       n1[i] = num1;
       n2[i] = num2;
       printf("%d %d\n", n1[i], n2[i]);
  }
  
  for( i = 0; i < N + 1; i++)
  {
       c[i] = sprintf(chara, "%d", n1[i]);
       printf("c[%d] = %c\n", i, c[i]);
  }
  
  
  free (n1);
  free(n2);
  free(c);
  fclose(fp);
  

  return 0;
}


I get:

0006 342
00061 344
00062 4237
00063 34
0007 322
1100 1
1101 324
11011 2142
7
6 342
61 344
62 4237
63 34
7 322
1100 1
1101 324
11011 2142
c[0] = ☺
c[1] = ☻
c[2] = ☻
c[3] = ☻
c[4] = ☺
c[5] = ♦
c[6] = ♦
c[7] = ♣


So...I'm scratching my head on this one. I want to maintain "0006" etc., but reading it in as an int converts 0006 into 6. But trying to read it as a char, apparently I'm not doing it correctly as the first case showed. Suggestions?
closed account (4jNqM4Gy)
Also, suggestions in C preferred even though I'll consider C++, but no other C[blah] please. Thanks.
Topic archived. No new replies allowed.