I did a program to read the output of the UNIX command ls -ali
and count the number of directories, write files, link files etc.
But there seeems to be something wrong with my code and I cant compile it. I cant seem to find out whats wrong with it.

This program is executed by entering the command ls -ali | ./a.out
So the output of the list is piped into my program.

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	char input[255];
	int countWrite = 0;
	int countLink = 0;
	int countDir = 0;
	int countSize = 0;
	string owners[255];
	char* s;		
	string pid,perm,dir,owner,group,size,date,file;	
	char d,l,w;
	
while (cin.getline(input,255,'\n'))
{
	s = input ;	
	[pid,perm,dir,owner,group,size,date,file] = strtok(s," ");
	//tokenize into substrings	
	
	if (perm == "d*")//count directories
		countDir++;

	if (perm == "l*")//count link files
		countLink++;

	if (perm == "*w*")//count writeable files
		countWrite++;
	
	for (int i = 0 ; i<255 ; i++)
		if (owners[i] != owner)
			owners[i] = owner;			


	size+=size;//count total size of files in bytes
	
	
		
} 


return 0;
}#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	char input[255];
	int countWrite = 0;
	int countLink = 0;
	int countDir = 0;
	int countSize = 0;
	string owners[255];
	char* s;		
	string pid,perm,dir,owner,group,size,date,file;	
	char d,l,w;
	
while (cin.getline(input,255,'\n'))
{
	s = input ;	
	[pid,perm,dir,owner,group,size,date,file] = strtok(s," ");
	//tokenize into substrings	
	
	if (perm == "d*")//count directories
		countDir++;

	if (perm == "l*")//count link files
		countLink++;

	if (perm == "*w*")//count writeable files
		countWrite++;
	
	for (int i = 0 ; i<255 ; i++)
		if (owners[i] != owner)
			owners[i] = owner;			


	size+=size;//count total size of files in bytes
	
	
		
} 


return 0;
}

Recommended Answers

All 11 Replies

Other than you have two mains ;)

you need to change the [ ] around the return value of strtok to ( )... don't count on it showing you anything though.... (you have no data output)

oh didnt notice i copied the code twice lol just ignore the copied one

>>[pid,perm,dir,owner,group,size,date,file] = strtok(s," ");
What in the world are you trying to do here? strtok() only returns one string, not multiple strings.

pid = strtok(s," "); // first time
perm = strtok(NULL, " ");
dir = strtok(NULL, " ");
// etc etc for each of the others

oh I did that because of an example I saw. And it's the only example out there which is in line with what I want to do...
which is the break the input line into different fields and check only specific fields.

s = '  This is a simple example.';
[token, remain] = strtok(s)
token =
   This
remain =
   is a simple example.

I have never seen this sort of thing and its hard to imagine C++ would include such a feature. Just for curiousity's sake, could you provide a link to where you found this example? And AncientDragon is right, you need to call strtok() multiple times.

It looks like an enhanced strtok() you might find in something like python or ruby, or some other scripting language.

ok here's my updated and corrected code. Compiles fine. But when I run the command ls -ali | ./a.out in Unix, I get a segmentation error. Am I missing a library?

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	char input[255];
	int countWrite = 0;
	int countLink = 0;
	int countDir = 0;
	string owners[255];
	char* s;		
	string pid,perm,dir,owner,group,size,date,file;	
	char d,l,w;
	
while (cin.getline(input,255,'\n'))//read lines from output of unix cmd ls -ali
{	
	s = input;	
	//tokenize into substrings
	pid = strtok(s, " ");
	perm = strtok(NULL, " ");
	dir = strtok(NULL, " ");
	owner = strtok(NULL, " ");
	group = strtok(NULL, " ");
	size = strtok(NULL, " ");
	date = strtok(NULL, " ");
	file = strtok(NULL, " ");
		
	
	if (perm == "d*")//count directories
		countDir++;

	if (perm == "l*")//count link files
		countLink++;

	if (perm == "*w*")//count writeable files
		countWrite++;
	
	for (int i = 0 ; i<255 ; i++)
		{if (owners[i] != owner)
			owners[i] = owner;}//collect all owners		


	size+=size;//count total size of files in bytes
	
	
		
} 
//print a report 
cout << "Total Directories = " << countDir << endl;
cout << "Total Link Files = " << countLink << endl;
cout << "Total Writeable Files = " << countWrite << endl;
cout << "Total file size = " << size << endl;
for(int i = 0;i<255;i++)
{
	cout << "Owners = " << owner[i] << endl;
}


return 0;
}

Your while loop, for loop, and cout's, you don't seem to think are part of your int main?

anyway, have you looked at the output of ls -ali? I see the distance between some of the columns in only one space.... but output of some of the others is not simply 1 space, but varies based on the length of the other column, and so forth and so on.

edit: oh, and don't forget the first line that is output: total 1532 (some number, mine is 1532).. yeah, you might want to discard that first read.

Sorry to back to back post (edit is now gone):

#include <iostream>
#include <cstring>
#include <vector>

using namespace std;

int main()
{
	char input[255];
	int countWrite = 0;
	int countLink = 0;
	int countDir = 0;
	string owners[255];
	char *s;
	char *result = NULL;
	string pid,perm,dir,owner,group,size,date,file,mtime;
	char d,l,w;
	
	while (cin.getline(input,255,'\n'))//read lines from output of unix cmd ls -ali
	{	
	
		vector<string> parts;
		std::string tmpstr(input);
		if (tmpstr.substr(0, 5) == "total") continue;	

		s = input;	

		result = strtok(s, " ");

		while (result != NULL)  {
			if (result != "" && result != " ") {
				parts.push_back(result);
			}

         		result = strtok(NULL, " ");
     		}


		pid = parts[0];
		perm = parts[1];
		dir = parts[2];
		owner = parts[3];
		group =parts[4];
		size = parts[5];
		date = parts[6];
		mtime = parts[7];
		file = parts[8];
		

		cout << "pid: " << pid << endl;
		cout << "perm: " << perm  << endl;
		cout << "dir: " << dir  << endl;
		cout << "owner: " << owner << endl;
		cout << "group: " << group << endl;
		cout << "size: " << size  << endl;
		cout << "date: " << date  << endl;
		cout << "time: " << mtime << endl;
		cout << "file: " << file << endl;


		// I dunno about the rest of your code, but it works up to here
		// This is a hack job... I didn't want to have to rewrite your 
		// entire code, so I made it work with what you have.

			
		if (perm == "d*")//count directories
			countDir++;

		if (perm == "l*")//count link files
			countLink++;

		if (perm == "*w*")//count writeable files
			countWrite++;
	
		for (int i = 0 ; i<255 ; i++) {
			if (owners[i] != owner)
				owners[i] = owner;
		}//collect all owners		


		size+=size;//count total size of files in bytes
	} 

	//print a report 
	cout << "Total Directories = " << countDir << endl;
	cout << "Total Link Files = " << countLink << endl;
	cout << "Total Writeable Files = " << countWrite << endl;
	cout << "Total file size = " << size << endl;

	for(int i = 0;i<255;i++) {
		cout << "Owners = " << owner[i] << endl;
	}

	return 0;
}

thanks for the help so far. I have changed all my test functions and all of them work except for counting the total size of files in bytes. I know that strings do not allow integer calculations. So, is there anyway to convert that token for file size into an integer? or is there another way to calculate ?

#include <iostream>
#include <cstring>
#include <vector>

using namespace std;

int main()
{
	char input[255];
	int countWrite=0;
	int countLink=0;
	int countDir=0;
	string owners[255];
	char *s;
	char *result = NULL;
	string pid,perm,dir,owner,group,fileSize,date,ufile,mtime;
	char d,l,w;
	
	while (cin.getline(input,255,'\n'))//read lines from output of unix cmd ls -ali
	{	
	
		vector<string> parts;
		std::string tmpstr(input);
		if (tmpstr.substr(0, 5) == "total") continue;	

		s = input;	

		result = strtok(s, " ");

		while (result != NULL)  
		{
			if (result != "" && result != " ") 
			{
				parts.push_back(result);
			}

         		result = strtok(NULL, " ");
     		}

		pid = parts[0];
		perm = parts[1];
		dir = parts[2];
		owner = parts[3];
		group =parts[4];
		fileSize = parts[5];
		date = parts[6];
		mtime = parts[7];
		ufile = parts[8];
		
		//count directories
		string::size_type loc1 = perm.find( "d", 0);
		if(loc1 != string::npos)
		{countDir++;}

		//count link files
		string::size_type loc2 = perm.find( "l", 0);
		if(loc2 != string::npos)
		{countLink++;}
	
		//count write files
		string::size_type loc3 = perm.find( "w", 0);
		if(loc3 != string::npos)
		{countWrite++;}
		
		char buf[30];
		memset(buf, '\0', 30);
		for(int i = 0;i<255;i++)		
		{
			owners[i] = owner;
			owners[i].copy(buf,25);
		}
		
		fileSize+=fileSize; //count total size of files in bytes
				    //does not work since its a string
	} 

	//print a report 
	cout << "Total Directories = " << countDir << endl;
	cout << "Total Link Files = " << countLink << endl;
	cout << "Total Writeable Files = " << countWrite << endl;
	cout << "Total file size = " << fileSize << endl;

	for(int i = 0;i<255;i++) 
	{	if (owners[i] != owners[i+1] | owners[i] != owners[i-1])
        	cout << "Owners = " << owners[i] << endl;
	}

	return 0;
}
int fileSize = strtoul(parts[5].data(), NULL, 0);

strtoul is defined in cstdlib

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.