Does scanf break on gigantic char tables? - c

I have a problem with reading string of triples digit-digit-space.
Relevant code (lib's may / may not be needed in this particular code):
#include <stdio.h>
#include <stdlib.h>
#define N 20
#define M 20
#define n (3*N*M)
int main()
{
char str_t[n];
scanf("%s", str_t);
for(i=0;i<n;i++)
printf("%c", str_t[i]);
return 0;
}
The input is as mentioned set of triples repeated 399 times finished with d-d, saved to char array[1200].
I assume that pasting into console is okay since I did it before. When it comes to printing back the array, I get random mumbo jumbo like: 3�X2���W2��#M!�
Input:
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 49 49 99
40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 81 49 31 73 55 79
14 29 93 71 40 67 53 88 30 03 49 13 36 65 52 70 95 23 04 60 11 42 69
24 68 56 01 32 56 71 37 02 36 91 22 31 16 71 51 67 63 89 41 92 36 54
22 40 40 28 66 33 13 80 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84
20 35 17 12 50 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38
64 70 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 24
55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 21 36 23 09
75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 78 17 53 28 22 75 31
67 15 94 03 80 04 62 16 14 09 53 56 92 16 39 05 42 96 35 31 47 55 58
88 24 00 17 54 24 36 29 85 57 86 56 00 48 35 71 89 07 05 44 44 37 44
60 21 58 51 54 17 58 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77
04 89 55 40 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98
66 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 04 42
16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 20 69 36 41 72
30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 20 73 35 29 78 31 90 01
74 31 49 71 48 86 81 16 23 57 05 54 01 70 54 71 83 51 54 69 16 92 33
48 61 43 52 01 89 19 67 48

From http://linux.die.net/man/3/scanf, concerning the %s format:
Matches a sequence of non-white-space characters... The input string
stops at white space

If the input consists of a single line, you can use fgets instead of scanf:
fgets(str_t, n, stdin);

Related

C function printing out additional values

I used the below C code in a question which asked to reverse the given array.
But it is outputing some additional values.
Please tell if there's a mistake in code.
Edit : Code passed all test cases after a newline after every test case, but I am still wondering why I was getting those additional values as output. Can any CS major explain.
#include <stdio.h>
int main() {
int t;
int n;
scanf("%d", &t);
while(t>0){
scanf("%d",&n);
int arr[n];
for(int i = 0; i<n; i++){
scanf("%d", &arr[i]);
}
for(int p = n-1; p>0; p--){
printf("%d ", arr[p]);
}
printf("%d", arr[0]);
t--;
}
return 0;
}
Input:
1
84
86 77 15 93 35 86 92 49 21 62 27 90 59 63 26 40 26 72 36 11 68 67 29 82 30 62 23 67 35 29 2 22 58 69 67 93 56 11 42 29 73 21 19 84 37 98 24 15 70 13 26 91 80 56 73 62 70 96 81 5 25 84 27 36 5 46 29 13 57 24 95 82 45 14 67 34 64 43 50 87 8 76 78 88
Expected Output :
88 78 76 8 87 50 43 64 34 67 14 45 82 95 24 57 13 29 46 5 36 27 84 25 5 81 96 70 62 73 56 80 91 26 13 70 15 24 98 37 84 19 21 73 29 42 11 56 93 67 69 58 22 2 29 35 67 23 62 30 82 29 67 68 11 36 72 26 40 26 63 59 90 27 62 21 49 92 86 35 93 15 77 86
My Output :
88 78 76 8 87 50 43 64 34 67 14 45 82 95 24 57 13 29 46 5 36 27 84 25 5 81 96 70 62 73 56 80 91 26 13 70 15 24 98 37 84 19 21 73 29 42 11 56 93 67 69 58 22 2 29 35 67 23 62 30 82 29 67 68 11 36 72 26 40 26 63 59 90 27 62 21 49 92 86 35 93 15 77 8624 64 34 0 93 50 41 28 64 88 79 55 21 51 46 45 18 ...

printing prime numbers from an array of 3 to 100

I don't get how to fix this code so that it works:
int Numbers_Given[97];
int n;
for (n = 3; n <= 100; ++n) {
Numbers_Given[n - 3] = n;
// printf("%d ", Numbers_Given[n - 3]);
}
int i;
for (n = 0; n < 97; n++) {
for (i = 2; i < Numbers_Given[i - 2]; i++) {
if (Numbers_Given[i - 2] % i == 0)
break;
else (printf("%d ", Numbers_Given[i - 2]));
}
}
return 0;
}
It seems like it's just not comprehending the %. What's going on? It prints out the original array from 3 to 100, over and over again. Prime numbers are not printed out.
There are multiple problems.
Your array is too small
You are using i-2 as index when you should use n
You are printing before you have checked all % values.
Try this:
int main()
{
int Numbers_Given[98]; // because highest index is 100-3 = 97
int n;
for (n=3;n<=100;++n)
{
Numbers_Given[n-3]=n;
}
int i;
for (n=0;n<=97;n++)
{
int prime = 1; // Assume that Numbers_Given[n] is a prime
for(i=2;i<Numbers_Given[n];i++) // use Numbers_Given[n]
{
if (Numbers_Given[n]%i==0)
{
prime = 0; // Not a prime so clear the flag
break;
}
}
if (prime) (printf("%d ", Numbers_Given[n])); // Print if it's a prime
}
return 0;
}
BTW: When checking the remainder (%) you are testing all numbers from 2 to Numbers_Given[n] - 1. You don't need that, you can stop earlier (i.e. sqrt(Numbers_Given[n]))
First problem, as #user3386109 pointed out, that you should use n<100 instead of n<=100 as Number_Given[97] is the array itself so last iteration go one past of it which doesn't make any difference in output but avoid using such is a good practice for future codes.
Here the problem is that in inner loop you seem to run it with condition i<Numbers_Given[i-2] but the problem is the moment you increase the value of i with i++ the value of Number_given[i-2] changes and so it never reaches the end. Let's say we take first iteration i=2 then after first iteration i++ changes it to i=3 but now Number_given[i-2] is referred to Number_given[1] which is 4 so still i<4 and condition follows so the loops runs and then the next loop i=4 but then again Numbers_Given[i-2] will be Numbers_Given[2] = 5 so it satisfies the condition i<5 again. Same goes for every loop. So you get the number range over and over.
To solve this change Numbers_Given[i-2] to Numbers_Given[n] as now after increment of i , n is independent of it and so doesn't change the value and strict the condition.
Moreover even after replacing Numbers_Given[i-2] to Numbers_Given[n] the problem is after failing to follow ' if (Numbers_Given[n]%i==0)' statement the else runs and output the number but it will continue to do so for every value of i so the output will look like
3 5 5 5 7 7 7 7 7 9 11 11 11 11 11 11 11 11 11 13 13 13 13 13 13 13 13 13 13 13 15 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 21 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 25 25 25 27 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 33 35 35 35 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 39 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 45 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 49 49 49 49 49 51 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 55 55 55 57 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 63 65 65 65 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 69 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 75 77 77 77 77 77 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 81 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 85 85 85 87 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 91 91 91 91 91 93 95 95 95 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 99
So to solve this we simply break our loop whenever it reaches the else statement meaning we get out prime number the first time we get it and then don't check it again.
So the final code will look like this which outputs all the prime numbers from an array of 3 to 100.
#include <stdio.h>
#include <stdbool.h>
int main()
{
int Numbers_Given[98];
int n;
for (n=3;n<=100;++n)
{
Numbers_Given[n-3]=n;
// printf("%d ", Numbers_Given[n-3]);
}
int i;
for (n=0;n<97;n++)
{
bool flag = 1;
for(i=2;i<Numbers_Given[n];i++){
if (Numbers_Given[n]%i==0){
flag = 0;
break;
}
}
if (flag) {
printf("%d ", Numbers_Given[n]);
}
}
return 0;
}
whose output:
3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
P.S:- As others said ask question with complete information like what you expect and instead what appears, error codes you get(if any), etc., lastly edit the question to make it easier for people to interpret.
One more thing 2 is a prime also, :) just a side info.

Send outputs with multiple variables from server to client in C

I want to send the printf's from my sorter function and main function as outputs to the client. I would really appreciate it if someone would tell me how to get the outputs on the client side instead of the server side since I tried using write() and vnsprintf() but i do not know how to send a string that contains variables in it using write() or vnsprintf(). For example
printf("Thread %d processes the %d array and the median is %.1fn",myStruct->threadNum, m + 1 + myStruct->arrayNum, median)
this code will print to the server terminal but I want it to print to the client terminal but since it has multiple variables, I do not understand how to pass it to the client.
SERVER CODE
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#define NUMTHREADS 4
///////////////////////STRUCTURE//////////////////////////////////
struct threadStruct {
int myArr[60][30];
int rowSizeLimiter[60];
int threadNum;
int arrayNum;
double medianSum;
};
/////////////////////QSORT COMPARE FUNCTION/////////////////////////
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
//////////////////////////////////FIND MEDIAN FUNCTION////////////////////////
double findMedian(int arr[], int arrLen) {
double median;
int mid, value;
value = (arrLen%2);
if(value == 1){
mid = (double)((arrLen/2) + 0.5);
median = arr[mid];
}
else{
mid = arrLen/2;
median = ((double)(arr[mid - 1] + arr[mid])/2);
}
return median;
}
//////////////////////SORTER FUNCTION/////////////////////////////
void* sorter(void *args){
struct threadStruct* myStruct = args;
int m, n;
double median;
int simpleArr[30];
myStruct->medianSum = 0;
for(m = 0; m < 60; m++){
for(n = 0; n < myStruct->rowSizeLimiter[m]; n++){
simpleArr[n] = myStruct->myArr[m][n];
}
qsort(simpleArr,myStruct->rowSizeLimiter[m], sizeof(int), cmpfunc);
for(n = 0; n < myStruct->rowSizeLimiter[m]; n++){
myStruct->myArr[m][n] = simpleArr[n];
}
median = findMedian(simpleArr, myStruct->rowSizeLimiter[m]);
myStruct->medianSum = median + myStruct->medianSum;
printf("Thread %d processes the %d array and the median is %.1f \n",myStruct->threadNum, m + 1 + myStruct->arrayNum, median);
}
printf("----------- Processes Finished for thread %d ----------- \n", myStruct->threadNum);
return NULL;
}
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
int myArray[240][30];
int cellTracker[240]; //This array holds the amount of values stored in each row of the 2d array. Its purpouse is to give a fixed length for each row.
char line[240];
char *token;
double totalMedianSum;
int i ,z ,j, k, count;
k = 0;
struct threadStruct myStruct[NUMTHREADS];
pthread_t thread[NUMTHREADS]; //threadID initialization
FILE *fp;
//////////////////////////READ////////////////////////////////////////////////////
buffer[strcspn(buffer, "\n")] = 0;
fp=fopen(buffer, "r");
i = 0;
while(fgets(line, sizeof(line), fp)){
j = 0;
token = strtok(line, " ");
while(1)
{
z = atoi(token);
myArray[i][j] = z;
token = strtok(NULL, " ");
cellTracker[i] += 1;
if (token==NULL) break;
j++;
}
count = i + 1;
i++;
}
printf("The number of arrays is %d", count);
printf("\n");
///////////////////////////Passing cellTracker to rowsize limiter/////////////////
for(i = 0; i<240; i++){
if(k>59){
k = 0;
}
if(i>=0 && i<60){
myStruct[0].rowSizeLimiter[k] = cellTracker[i];
k++;
}
else if(i>=60 && i<120){
myStruct[1].rowSizeLimiter[k] = cellTracker[i];
k++;
}
else if(i>=120 && i<180){
myStruct[2].rowSizeLimiter[k] = cellTracker[i];
k++;
}
else if(i>=180 && i<240){
myStruct[3].rowSizeLimiter[k] = cellTracker[i];
k++;
}
}
///////////////////////////LOOP FOR SPLITTING ARRAY INTO 4 SMALLER ARRAYS/////////
for(i=0;i<60;i++){
for(k=0;k<cellTracker[i];k++){
myStruct[0].myArr[i][k] = myArray[i][k];
}
}
for(i=60;i<120;i++){
for(k=0;k<cellTracker[i];k++){
myStruct[1].myArr[i-60][k] = myArray[i][k];
}
}
for(i=120;i<180;i++){
for(k=0;k<cellTracker[i];k++){
myStruct[2].myArr[i-120][k] = myArray[i][k];
}
}
for(i=180;i<240;i++){
for(k=0;k<cellTracker[i];k++){
myStruct[3].myArr[i-180][k] = myArray[i][k];
}
}
myStruct[0].arrayNum = 0;
myStruct[1].arrayNum = 60;
myStruct[2].arrayNum = 120;
myStruct[3].arrayNum = 180;
///////////////////////Creating the threads////////////////////////////
for(i = 0; i< NUMTHREADS; i++){
myStruct[i].threadNum = i + 1;
pthread_create(&thread[i], NULL, sorter, &myStruct[i]);
pthread_join(thread[i], NULL);
totalMedianSum += myStruct[i].medianSum;
}
printf("\n");
printf("The sum of all median values is %.1f \n", totalMedianSum);
close(sockfd);
return 0;
}
CLIENT CODE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Please enter the file name: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
FILE CONTENT
1 98 48 55 46 12 48 43 7 73 47 33
97 26 67 25 67 47 46 74 67 43 78 98 90 58 6 5 53 19 37 42
81 84 36 70 59 65 99 56 94 23
79 73 27 47 98 78 8 2 3 43 84 19 59 98 51 72 2 13 55 3
20 61 25 84 28 70 56 23 52 69
86 70 60 90 72
51 71 92 91 55 6 72 67 73 64 78 43 65 30 49
99 82 40 72 5 44 20 21 22 72 99 74 27 59 25 1 26 26 22 66
63 27 54 46 46
91 65 77 45 94 94 95 11 77 46 64 14
69 70 75 48 68 22 55 78 1 4
31 76 55 12 93
15 28 25 91 44 5 67
81 50 84 9 26 29 98 5 86 92
60 54 52 66 49 22 73 47 84 82 84 63 12 12 19
27 34 89 16 41 85 56 76 1 49 74 80 59
68 75 95 21 25 29 49 27
16 99 68 11 10 49 90 57 84 98 56 88 19 66 44 14 32 35 17 93
30 95 24 23 60 94 28 27 10 98 11 52
73 24 76 72 86 79 74 50 59 58
81 25 48 57 62
16 50 78 84 32 14 37
76 49 20 28 92 55 34 92 14 43 13 27 64 95 91 2 14 49 93 32
1 18 79 79 92 15 42 71 72 52 35 26 96 87 97 58 33 5 2 45
37 69 46 6 67 15 89
30 14 36 22 26 96 72 34 82 65 69 50 98 3 67
16 36 64 41 71 64 96 90 50 74 36 65
37 70 4 36 68 22 65 41 65 90
100 90 85 90 30 91 9 99 70 90 35 96 98 29 13 83 65 44 58 70
93 62 29 95 6 66 1 53 28 72 21 5 36
65 31 40 58 96 89 31 1 66 31 31 81 10 15 86
26 62 35 70 7 71 73 94 29 100 36 47 34 97 73 22 60 93 82 55
98 72 21 47 48 88 87 31 28 44 62 47
82 63 39 23 7 79 51
35 70 58 84 48 65 58 30 43 43 31 52 12 23 3
49 56 50 92 41 50 36 49 31 79
77 2 57 94 85 97 87 36 59 45 10 46 55 51 71
70 47 10 35 75 44 54 93 46 27
22 51 84 98 6 73 70 73 28 57 42 85 53
36 24 88 16 64 6 22
43 95 87 92 98
77 14 32 19 44 7 32 48 65 47 42 69 76 62 100 51 66 78 1 24
32 66 96 1 45 86 98 52 31 17 13 97
95 68 19 79 89 23 53
6 2 46 61 86 87 79
56 99 67 31 41 45 42
65 98 14 76 24 23 36 38 43 33
31 60 72 41 89 95 67 42 51 77 12 46
76 91 11 60 92 63 92 21 27 43
95 14 63 40 78 25 42 100 42 12
24 35 27 20 49 45 73 58 2 11
16 34 83 12 42 4 84
83 48 61 84 58 31 56 81 8 93 55 69 99 98 82 11 75 52 1 91
35 3 98 85 57 50 9 62 24 65 99 49 65
100 61 49 67 49 70 13 56
44 34 5 79 80 43 99 77 24 71 79 85
15 60 24 61 4 58 69 97 60 93 90 49 62 30 39 69 72 50 30 36
98 6 98 36 79 72 30 74 45 43 14 73 90 5 91
51 4 1 96 68 68 68 35 5 3 91 87 65
1 33 8 4 16 85 22 46 39 81 94 5 73 57 92
28 91 79 93 46 53 49 73
31 51 23 23 8 98 6 77
84 67 55 25 52
11 57 7 80 58 60 74 85 68 19 64 10 48 48 9
62 30 55 69 91
86 97 20 47 11 85 27 79 83 69 45 23
75 65 60 95 100 25 59
97 62 14 60 63 46 34 96
13 32 49 75 12 18 87 4 10 56 68 95 90 38 65
56 43 74 27 3 88 67 75 91 33 100 58 68 72 67 58 83 1 79 28
43 5 57 14 54
4 50 47 96 98 95 37
76 32 97 41 90 48 97 39 97 7
75 16 7 95 5 85 64 10 98 70 4 60 79 82 42 40 85 67 8 43
56 5 52 73 56 78 44 76
12 2 14 46 65 97 62 33
62 52 61 63 36
32 53 79 15 76 96 45 17 16 72
79 86 41 21 4 38 64 99 79 38 54 58 100 31 39 88 41 49 11 37
90 12 87 99 97 72 87 68 84 15 100 98 45 62 9 62 99 33 3 17
34 45 72 65 3 89 79 83 50 81 46 82 54
12 68 69 36 8 4 70 63 18 12
51 74 4 60 58 28 69 43 26 96 80 34 45 88 14 23 4 92 69 28
87 8 87 74 68 84 82 27 58 86 21 27 18
67 58 17 38 35 99 19 61
98 42 97 52 39 73 33 75 36 66 63 5 31
91 52 99 73 84 24 32 57 77 91 61 24 42 42 70 2 5 55 22 45
41 9 43 53 59 60 48
49 2 85 53 25
6 28 17 6 88 71 62 43 19 68
52 96 31 92 68 26 88 34 49 54 3 50 50
59 92 17 77 66 59 35 6 49 6 74 99 65
1 7 97 78 18 2 2 99 78 82 1 44 53
39 63 86 88 38 48 58
59 72 37 80 25 32 56 37 24 82 74 85
48 14 64 9 64 97 60 63 25 85 42 96 70 55 56 94 1 29 16 54
51 41 21 71 60 75 55
33 37 32 43 49 69 56 93 4 1 82 60 93
71 59 98 79 67 2 86 76 87 1 49 66
100 59 56 94 4 44 66 6 22 23 19 46 56 7 23 23 71 97 10 10
62 37 86 57 64
45 62 80 49 66 86 97 64
41 26 82 38 45 32 24 97 45 82 23 72 90 11 67
16 56 1 6 85 89 92 12 43 50 99 73
60 27 21 40 47 68 58 35 89 37 51 34 42 51 83 93 100 91 47 4
38 66 67 76 51 47 78 55 18 85 91 28
65 99 3 48 97 21 82
29 13 85 68 37 84 37 8 45 94 26 51 40 27 68 31 45 78 52 50
66 74 67 81 74 40 46
23 80 42 33 57 8 46 21 78 99
31 11 96 37 21
36 97 75 57 17 20 19 77 62 21 54 24 27 41 98 75 97 45 78 3
98 94 51 87 51 57 79 2 57 79 3 17 68 32 27
35 50 10 90 65 63 61 80 72 5 32 16 19
87 50 91 100 71 60 36 3 89 77
4 17 81 73 54 78 70 48 63 74 78 73 82 57 19 92 15 47 33 98
48 92 89 20 56 21 64 86 96 48 99 58 89 37 14
67 48 24 47 63 40 58 67 15 67 15 97 58
64 91 43 36 20 46 86
74 11 43 16 23 97 4 67 81 84 66 15 46 21 4 54 63 47 45 80
13 19 56 97 80 48 92 56 89 40 77 58 50 92 8
49 23 49 22 4 42 55 15 36 63 88 82
100 40 41 5 59 64 37 39 82 91 25 80 66 91 31 42 6 70 14 94
82 75 11 57 9 70 23 36
33 16 6 84 4 5 69 21 65 24 43 64 19
82 86 16 45 93 41 84 4 45 2 63 18 27 68 45
43 52 44 35 45 86 71 85 42 31 83 27
26 87 97 100 54
99 45 52 70 80 13 54 37 52 62 100 56
63 8 7 32 45 13 13 16 8 11 64 11
37 20 16 61 25
42 78 37 78 32 79 99 70 5 61 61 60 73 5 30
26 28 67 32 55 35 92
9 79 79 8 82
22 92 36 11 82 16 37
84 88 43 78 22 73 95 93 18 73 37 16
43 100 54 6 23 48 82 6 42 20
69 25 39 74 13
24 78 33 18 34 51 79 13 20 89 18 64 29 77 2
3 84 14 34 92
56 94 21 12 27 34 54 35 63 67 83 50
55 46 60 39 24 37 98 15 74 53
69 73 75 29 88 63 44 26 19 15 72 52 54 33 100
98 75 70 78 22 26 82 35 68 22 57 39 55 52 38
16 52 50 33 79 11 62 18 42 82
32 58 100 18 58 5 37 80
10 27 39 79 46 26 34 20 54 58 61 59 61
59 71 42 62 78 52 9
17 86 8 43 98
86 6 12 17 29 15 70 1 60 86 70 84 50 15 71
65 3 43 17 74 53 38 74 29 13 20 54
23 24 56 71 59 38 55 89 49 18 84 87 76 46 5
27 74 90 26 68 60 27
36 10 62 64 60 66 67 45 81 37
68 21 36 81 42 15 17 29 6 17 86 47 82 71 40 38 54 94 27 3
76 66 84 13 98 27 13 70
95 21 34 78 13 28 27 13 39 47 62 84 99 4 18
96 37 44 86 10 69 79 62
6 82 50 59 6 33 58 7 34 71 63 34 100
30 99 52 81 67
48 75 31 16 64 28 93 7
61 79 9 25 96 17 41 44
41 76 22 37 92 19 62 47 22 55 56 54 80
48 72 18 73 58 47 9 74 20 71 64 93 39 93 75 97 99 9 100 57
38 51 35 91 19 96 75 29 53 76 70 74 37 68 97 88 47 85 12 45
41 25 53 67 63
55 47 70 17 63 52 44 30 41 80 2 41 16
65 12 23 40 60 62 54 16
46 97 29 84 35 93 97
3 11 33 86 36 62 44 31 71 26
12 45 46 79 94 11 89 62 60 76 28 96 6 92 72 69 15 34 97 84
49 70 77 45 31 98 61 61
3 43 31 18 44 99 3
29 16 57 33 90 81 34 29 82 59 58 72
35 4 78 8 17 67 39 78
56 8 80 21 86 41 14 54 12 67 51 5 94
76 51 6 14 19 47 86 74 31 49 94 38 58
50 5 18 49 31 76 4
34 90 57 10 41 10 53
90 7 17 85 75 2 70 16 22 76 60 71 93
68 21 54 18 60 90 59 74 8 31 34 63 9
58 45 92 19 10 78 37 22 60 73 96 93
13 27 3 72 33 58 50
1 94 13 6 75 76 74
23 84 5 1 38 41 42 37 90 54 43 14
84 66 6 59 6 37 47 62
36 52 25 52 75 53 26 76
51 52 18 33 36 91 47 47 44 34 25 70
79 77 19 57 78 95 38 62
10 99 53 45 7 43 18 83
85 33 30 11 66 54 5 76 82 48 70 57 79 89 61
21 49 99 41 51 4 2 35 19 24 11 76 9
99 34 1 13 85 11 60 91
5 62 58 100 81
99 31 36 41 16 35 46 17 39 98 44 22
92 5 48 49 47 10 91
64 80 81 16 73 35 99 16 14 32
55 66 70 74 98 80 6 37 46 99 64 63 18 11 86
88 92 60 88 32 94 60 36 14 25 48 71
68 20 32 89 72 39 2 4 15 12 79 72
99 60 86 50 88
32 45 100 16 10 100 45 52 47 41 87 46 54 70 49
61 84 34 18 8
60 14 33 11 88
89 94 5 32 89 60 24 86 23 45 25 17
1 43 3 78 83 8 32 55 75 61 53 21 25
96 7 57 5 36 6 84 10 71 38 93 38 14 57 65
13 65 47 27 53 29 60 40 55 28 86 48 60
25 44 29 21 6 65 47
81 58 95 15 78 55 21 63 62 6
30 99 63 5 47 23 89 4 97 41 73 54 54
41 46 27 52 27
37 91 72 54 32
96 2 57 13 38 81 3 69 5 43
69 22 40 32 25
48 53 73 29 72 44 3 96 64 62 36 11 24 70 80
76 44 60 65 64 49 53 22
89 48 74 69 98 90 82 36 58 10 93 72
79 56 70 77 46 53 86 4 60 51 61 46 89
43 40 71 84 23 74 64 73
96 29 14 31 22 78 21 77
57 100 4 39 92 42 30 24
51 54 25 93 86 55 39 38 46 65 83 6
69 7 71 95 62 21 14
55 1 89 57 86
93 79 6 56 21 10 2 87
73 36 54 12 64 86 28 56 57 26
13 90 52 8 59 88 32 16 46 39 69 99 14 76 25
74 19 69 24 27 74 65 82 2 42 58 73 47 83 13 80 19 56 83 98
96 47 71 4 65 39 15 58 90 10 94 95 64
39 78 21 67 4
6 46 36 28 87 49 89 22 91 81
60 32 45 100 55 30 51 31 29 55
89 54 7 41 31 68 48 77
88 13 82 78 86
27 58 88 13 57 33 57 93 14 25 62 19 100 86 26
72 64 20 51 32 19 39 95 69 71
7 86 21 98 51 12 47 71
13 42 57 51 82 66 65 21 6 2 83 35 25 10 28
82 30 33 29 77 91 98 55 65 40 4 9 21

Populating 2d array of ints from string in C

I want to populate a 2d array of ints with some numbers.
The numbers is in a grid format like the following :
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
I want my program to take the string above and store the numbers in a 20x20 2d array of ints.
int main(void)
{
int grid[20][20];
for(int i = 0;i<20;i++)
{
for(int j = 0;j<20;j++)
{
grid[i][j] = //some code to populate int here
}
}
}
I am unsure how to get the 'code to populate'
So I tried using strtok as below:
int main(void)
{
char *input = "08 02 22...48";
char *output = strtok(input," ");
printf("%s",output);
}
However, the above is giving me a segmentation fault and I am unsure why.
I am very new to programming, especially in C, and I am a bit unsure how to get an input like above stored as a 2d array of ints. Any alternative routes to the above or any guidance as to why I am getting segmentation faults is appreciated, thanks :)
You're almost there. Inside your inner loop,
if (scanf("%d", &grid[i][j]) < 1)
break; // oops, looks like we ran out of numbers to read!
The reason that strtok is giving you a segmentation fault is that you are using a const char* as the input, but strtok expects to modify the string (namely, it inserts a '\0' at the first instance of the terminating character). If you just changed your code to
char input[] = "08 02 22...48";
char *output = strtok(input," ");
printf("%s",output);
You would find that it works (because that initializer creates a string that is not a const).
Obviously you can then use sscanf to convert the string to a numerical value - make sure that you pass it the address of the location where you want to store:
sscanf(output, "%d", &grid[i][j]);
You look like you know how to combine these elements into a loop structure. Do note that strtok should be called with a char* argument the first time, and with NULL after that...
EDIT re-reading your question, it seems you would benefit from a complete code example:
#include <stdio.h>
#include <string.h>
int main(void) {
char input[]=\
"08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 "\
"49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 "\
"81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 "\
"52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 "\
"22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 "\
"24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 "\
"32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 "\
"67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 "\
"24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 "\
"21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 "\
"78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 "\
"16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 "\
"86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 "\
"19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 "\
"04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 "\
"88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 "\
"04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 "\
"20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 "\
"20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 "\
"01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48";
int ii, jj;
int grid[20][20];
char *s = strtok(input, " ");
for(ii=0; ii<20; ii++){
for(jj=0; jj<20; jj++){
sscanf(s, "%d", &grid[ii][jj]);
s = strtok(NULL, " ");
}
}
for(ii=0; ii<20; ii++){
for(jj=0; jj<20; jj++){
printf("%02d ", grid[ii][jj]);
}
printf("\n");
}
return 0;
}
Let me know if any of this needs clarification.
You may not apply function strtok to string literals. There is a more simple and robust approach by means of function strtol .
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
#define N 20
int main(void)
{
char *s =
"08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 "
"49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 "
"81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 "
"52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 "
"22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 "
"24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 "
"32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 "
"67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 "
"24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 "
"21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 "
"78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 "
"16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 "
"86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 "
"19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 "
"04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 "
"88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 "
"04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 "
"20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 "
"20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 "
"01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48 ";
int a[N][N] = { { 0 } };
int *p = ( int * )a;
const char *nptr = NULL;
char *endptr = s;
for ( size_t i = 0; i < N * N && nptr != endptr; i++ )
{
int x;
nptr = endptr;
x = ( int ) strtol( nptr, &endptr, 10 );
if ( nptr != endptr ) p[i] = x;
}
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ ) printf( "%3d", a[i][j] );
puts( "" );
}
return 0;
}
And this is its output
8 2 22 97 38 15 0 40 0 75 4 5 7 78 52 12 50 77 91 8
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 4 56 62 0
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 3 49 13 36 65
52 70 95 23 4 60 11 42 69 24 68 56 1 32 56 71 37 2 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 3 45 2 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 2 62 12 20 95 63 94 39 63 8 40 91 66 49 94 21
24 55 58 5 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 9 75 0 76 44 20 45 35 14 0 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 3 80 4 62 16 14 9 53 56 92
16 39 5 42 96 35 31 47 55 58 88 24 0 17 54 24 36 29 85 57
86 56 0 48 35 71 89 7 5 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 5 94 47 69 28 73 92 13 86 52 17 77 4 89 55 40
4 52 8 83 97 35 99 16 7 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 3 46 33 67 46 55 12 32 63 93 53 69
4 42 16 73 38 25 39 11 24 94 72 18 8 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 4 36 16
20 73 35 29 78 31 90 1 74 31 49 71 48 86 81 16 23 57 5 54
1 70 54 71 83 51 54 69 16 92 33 48 61 43 52 1 89 19 67 48
#include <stdio.h>
#include <ctype.h>
int populate(const char **p){
int n = 0;
while(isspace(**p))
++*p;
for(n=0; isdigit(**p); ++*p)
n = n * 10 + **p - '0';
return n;
}
int main() {
const char *numbers =
"08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 "
"49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 "
"81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 "
"52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 "
"22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 "
"24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 "
"32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 "
"67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 "
"24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 "
"21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 "
"78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 "
"16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 "
"86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 "
"19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 "
"04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 "
"88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 "
"04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 "
"20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 "
"20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 "
"01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48";
const char *p = numbers;
int grid[20][20];
for(int i = 0;i<20;i++){
for(int j = 0;j<20;j++){
grid[i][j] = populate(&p);
printf("%02d ", grid[i][j]);
}
printf("\n");
}
return 0;
}

How to print the name of the files inside an archive file?

I'm new to C and system programming. I want to open an archive file and print out the name of the files inside the archive file (e.g., my archive file is weds.a; inside weds.a, I have thurs.txt and fri.txt". I want to create an output that shows
thurs.txt
fri.txt
EDITED: It should work like the ar -t command.
Can someone give me some tips on how to do it? I've been reading the man page and looking for examples online, but I'm getting no where. I believe I'm missing something. The code I have below only prints the link count. Can someone help? Thanks in advance for your help!!
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/utsname.h>
#include <ctype.h>
#include <string.h>
int main (int argc, char **argv)
{
int in_fd;
struct stat sb;
if (argc != 2) {
printf("Error", argv[0]);
exit(EXIT_FAILURE);
}
if (stat(argv[1], &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE); //change from EXIT_SUCCESS to EXIT_FAILURE
}
//open the archive file (e.g., hw.a)
in_fd = open(argv[1], O_RDONLY);
if (in_fd == -1)
{
perror("Can't open input file\n");
exit(-1);
}
printf("Link Count: %ld\n", (long)sb.st_nlink);
return 0;
}
The easiest way is to use the ar program to list the names:
ar -tv weds.a
The - is optional; the v means you'll get size and time information.
If you want to get into reading the archive file itself, you'll have to be aware of the differences in the formats on different systems. The relevant header is (normally) <ar.h>. I have information for a number of systems, many of them obsolete, and there are a variety of different tricks used for handling long file names (and other even more basic file format issues) but you may have a more limited scope in mind. Any such work based on <ar.h> will be non-trivial; you're best off reusing what already exists (the ar program) if at all possible.
This is an archive from a Mac OS X 10.8.4 machine.
$ cat thurs.txt
0123456789:;<=>?#ABCDEFGHIJKLMNO
$ cat fri.txt
PQRSTUVWXYZ[\]^_`abcdefghijklmno
$ odx weds.a
0x0000: 21 3C 61 72 63 68 3E 0A 74 68 75 72 73 2E 74 78 !<arch>.thurs.tx
0x0010: 74 20 20 20 20 20 20 20 31 33 37 34 30 39 36 30 t 13740960
0x0020: 31 32 20 20 32 38 37 36 20 20 35 30 30 30 20 20 12 2876 5000
0x0030: 31 30 30 36 34 34 20 20 33 33 20 20 20 20 20 20 100644 33
0x0040: 20 20 60 0A 30 31 32 33 34 35 36 37 38 39 3A 3B `.0123456789:;
0x0050: 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B <=>?#ABCDEFGHIJK
0x0060: 4C 4D 4E 4F 0A 0A 66 72 69 2E 74 78 74 20 20 20 LMNO..fri.txt
0x0070: 20 20 20 20 20 20 31 33 37 34 30 39 36 30 30 35 1374096005
0x0080: 20 20 32 38 37 36 20 20 35 30 30 30 20 20 31 30 2876 5000 10
0x0090: 30 36 34 34 20 20 33 33 20 20 20 20 20 20 20 20 0644 33
0x00A0: 60 0A 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D `.PQRSTUVWXYZ[\]
0x00B0: 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D ^_`abcdefghijklm
0x00C0: 6E 6F 0A 0A no..
0x00C4:
$
Fortunately for you, the same files produce essentially the same archive on Linux too. In the Linux header <ar.h> you find:
/* Archive files start with the ARMAG identifying string. Then follows a
`struct ar_hdr', and as many bytes of member file data as its `ar_size'
member indicates, for each member file. */
#define ARMAG "!<arch>\n" /* String that begins an archive file. */
#define SARMAG 8 /* Size of that string. */
#define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
struct ar_hdr
{
char ar_name[16]; /* Member file name, sometimes / terminated. */
char ar_date[12]; /* File date, decimal seconds since Epoch. */
char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */
char ar_mode[8]; /* File mode, in ASCII octal. */
char ar_size[10]; /* File size, in ASCII decimal. */
char ar_fmag[2]; /* Always contains ARFMAG. */
};
The Mac OS X header has the same structure and ARMAG and ARFMAG values, but one extra macro:
#define AR_EFMT1 "#1/" /* extended format #1 */
You can see the ARMAG string at the start of the file. Each file is then preceded by a struct ar_hdr. Note that the example names here are blank terminated, not slash terminated.
After that, you find the data for the file. You can read the header in its entirety. Note that if any of the names reaches above 15 characters, or if a name contains spaces, then you get an extra entry at the start of the archive file that contains the file name strings, and you also get a modified name entry in the per-file header that identifies the relevant string in the string table.
Linux archive with long names etc
0x0000: 21 3C 61 72 63 68 3E 0A 2F 2F 20 20 20 20 20 20 !<arch>.//
0x0010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
* (1)
0x0030: 20 20 20 20 20 20 20 20 34 36 20 20 20 20 20 20 46
0x0040: 20 20 60 0A 66 69 6C 74 65 72 2E 73 74 64 65 72 `.filter.stder
0x0050: 72 2E 73 68 2F 0A 6C 6F 6E 67 20 6E 61 6D 65 20 r.sh/.long name
0x0060: 77 69 74 68 20 73 70 61 63 65 73 2E 74 78 74 2F with spaces.txt/
0x0070: 0A 0A 74 68 75 72 73 2E 74 78 74 2F 20 20 20 20 ..thurs.txt/
0x0080: 20 20 31 33 37 34 30 39 36 32 31 31 20 20 31 39 1374096211 19
0x0090: 39 34 38 34 35 30 30 30 20 20 31 30 30 36 34 30 94845000 100640
0x00A0: 20 20 33 33 20 20 20 20 20 20 20 20 60 0A 30 31 33 `.01
0x00B0: 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 23456789:;<=>?#A
0x00C0: 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 0A 0A BCDEFGHIJKLMNO..
0x00D0: 66 72 69 2E 74 78 74 2F 20 20 20 20 20 20 20 20 fri.txt/
0x00E0: 31 33 37 34 30 39 36 31 39 37 20 20 31 39 39 34 1374096197 1994
0x00F0: 38 34 35 30 30 30 20 20 31 30 30 36 34 30 20 20 845000 100640
0x0100: 33 33 20 20 20 20 20 20 20 20 60 0A 50 51 52 53 33 `.PQRS
0x0110: 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 TUVWXYZ[\]^_`abc
0x0120: 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 0A 0A 2F 30 defghijklmno../0
0x0130: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 31 33 13
0x0140: 37 31 31 34 35 35 38 34 20 20 31 39 39 34 38 34 71145584 199484
0x0150: 35 30 30 30 20 20 31 30 30 36 34 30 20 20 32 33 5000 100640 23
0x0160: 30 20 20 20 20 20 20 20 60 0A 23 21 2F 62 69 6E 0 `.#!/bin
0x0170: 2F 62 61 73 68 0A 73 65 74 20 2D 78 0A 72 6D 20 /bash.set -x.rm
0x0180: 2D 66 20 6F 75 74 2E 5B 31 32 33 5D 0A 2E 2F 67 -f out.[123]../g
0x0190: 65 6E 6F 75 74 65 72 72 2E 73 68 20 31 3E 2F 64 enouterr.sh 1>/d
0x01A0: 65 76 2F 6E 75 6C 6C 0A 2E 2F 67 65 6E 6F 75 74 ev/null../genout
0x01B0: 65 72 72 2E 73 68 20 32 3E 2F 64 65 76 2F 6E 75 err.sh 2>/dev/nu
0x01C0: 6C 6C 0A 28 20 2E 2F 67 65 6E 6F 75 74 65 72 72 ll.( ./genouterr
0x01D0: 2E 73 68 20 32 3E 26 31 20 31 3E 26 33 20 7C 20 .sh 2>&1 1>&3 |
0x01E0: 67 72 65 70 20 27 5B 30 2D 39 5D 30 27 20 3E 26 grep '[0-9]0' >&
0x01F0: 32 29 20 33 3E 6F 75 74 2E 33 20 32 3E 6F 75 74 2) 3>out.3 2>out
0x0200: 2E 32 20 31 3E 6F 75 74 2E 31 0A 6C 73 20 2D 6C .2 1>out.1.ls -l
0x0210: 20 6F 75 74 2E 5B 31 32 33 5D 0A 28 20 2E 2F 67 out.[123].( ./g
0x0220: 65 6E 6F 75 74 65 72 72 2E 73 68 20 32 3E 26 31 enouterr.sh 2>&1
0x0230: 20 31 3E 26 33 20 7C 20 67 72 65 70 20 27 5B 30 1>&3 | grep '[0
0x0240: 2D 39 5D 30 27 20 3E 26 32 29 20 33 3E 26 31 0A -9]0' >&2) 3>&1.
0x0250: 2F 31 38 20 20 20 20 20 20 20 20 20 20 20 20 20 /18
0x0260: 31 33 37 34 30 39 36 35 37 37 20 20 31 39 39 34 1374096577 1994
0x0270: 38 34 35 30 30 30 20 20 31 30 30 36 34 30 20 20 845000 100640
0x0280: 33 33 20 20 20 20 20 20 20 20 60 0A 30 31 32 33 33 `.0123
0x0290: 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 456789:;<=>?#ABC
0x02A0: 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 0A 0A DEFGHIJKLMNO..
0x02AE:
Mac OS X archive with long names etc
0x0000: 21 3C 61 72 63 68 3E 0A 74 68 75 72 73 2E 74 78 !<arch>.thurs.tx
0x0010: 74 20 20 20 20 20 20 20 31 33 37 34 30 39 36 30 t 13740960
0x0020: 31 32 20 20 32 38 37 36 20 20 35 30 30 30 20 20 12 2876 5000
0x0030: 31 30 30 36 34 34 20 20 33 33 20 20 20 20 20 20 100644 33
0x0040: 20 20 60 0A 30 31 32 33 34 35 36 37 38 39 3A 3B `.0123456789:;
0x0050: 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B <=>?#ABCDEFGHIJK
0x0060: 4C 4D 4E 4F 0A 0A 66 72 69 2E 74 78 74 20 20 20 LMNO..fri.txt
0x0070: 20 20 20 20 20 20 31 33 37 34 30 39 36 30 30 35 1374096005
0x0080: 20 20 32 38 37 36 20 20 35 30 30 30 20 20 31 30 2876 5000 10
0x0090: 30 36 34 34 20 20 33 33 20 20 20 20 20 20 20 20 0644 33
0x00A0: 60 0A 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D `.PQRSTUVWXYZ[\]
0x00B0: 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D ^_`abcdefghijklm
0x00C0: 6E 6F 0A 0A 66 69 6C 74 65 72 2E 73 74 64 65 72 no..filter.stder
0x00D0: 72 2E 73 68 31 33 37 34 30 39 37 37 39 34 20 20 r.sh1374097794
0x00E0: 32 38 37 36 20 20 35 30 30 30 20 20 31 30 30 36 2876 5000 1006
0x00F0: 34 34 20 20 32 33 30 20 20 20 20 20 20 20 60 0A 44 230 `.
0x0100: 23 21 2F 62 69 6E 2F 62 61 73 68 0A 73 65 74 20 #!/bin/bash.set
0x0110: 2D 78 0A 72 6D 20 2D 66 20 6F 75 74 2E 5B 31 32 -x.rm -f out.[12
0x0120: 33 5D 0A 2E 2F 67 65 6E 6F 75 74 65 72 72 2E 73 3]../genouterr.s
0x0130: 68 20 31 3E 2F 64 65 76 2F 6E 75 6C 6C 0A 2E 2F h 1>/dev/null../
0x0140: 67 65 6E 6F 75 74 65 72 72 2E 73 68 20 32 3E 2F genouterr.sh 2>/
0x0150: 64 65 76 2F 6E 75 6C 6C 0A 28 20 2E 2F 67 65 6E dev/null.( ./gen
0x0160: 6F 75 74 65 72 72 2E 73 68 20 32 3E 26 31 20 31 outerr.sh 2>&1 1
0x0170: 3E 26 33 20 7C 20 67 72 65 70 20 27 5B 30 2D 39 >&3 | grep '[0-9
0x0180: 5D 30 27 20 3E 26 32 29 20 33 3E 6F 75 74 2E 33 ]0' >&2) 3>out.3
0x0190: 20 32 3E 6F 75 74 2E 32 20 31 3E 6F 75 74 2E 31 2>out.2 1>out.1
0x01A0: 0A 6C 73 20 2D 6C 20 6F 75 74 2E 5B 31 32 33 5D .ls -l out.[123]
0x01B0: 0A 28 20 2E 2F 67 65 6E 6F 75 74 65 72 72 2E 73 .( ./genouterr.s
0x01C0: 68 20 32 3E 26 31 20 31 3E 26 33 20 7C 20 67 72 h 2>&1 1>&3 | gr
0x01D0: 65 70 20 27 5B 30 2D 39 5D 30 27 20 3E 26 32 29 ep '[0-9]0' >&2)
0x01E0: 20 33 3E 26 31 0A 23 31 2F 32 38 20 20 20 20 20 3>&1.#1/28
0x01F0: 20 20 20 20 20 20 31 33 37 34 30 39 37 38 32 32 1374097822
0x0200: 20 20 32 38 37 36 20 20 35 30 30 30 20 20 31 30 2876 5000 10
0x0210: 30 36 34 34 20 20 36 31 20 20 20 20 20 20 20 20 0644 61
0x0220: 60 0A 6C 6F 6E 67 20 6E 61 6D 65 20 77 69 74 68 `.long name with
0x0230: 20 73 70 61 63 65 73 2E 74 78 74 00 00 00 30 31 spaces.txt...01
0x0240: 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 23456789:;<=>?#A
0x0250: 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 0A 0A BCDEFGHIJKLMNO..
0x0260:
Differences
The Linux archive has a list of strings at the top of the file that have to be remembered. The Mac OS X archive has the special entry #1/28 which identifies the header as being followed by a 28-byte entry containing the file name (null padded to a multiple of 4 bytes; the length given includes the null padding). The Mac archive has no space after the name when it is exactly 16 characters long; the Linux archive puts the 16-character name into the string table.

Resources