0

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;
}
5
Contributors
11
Replies
12
Views
8 Years
Discussion Span
Last Post by death_oclock
0

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)

0

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

0

>>[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
0

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.
0

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.

0

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

0

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;
}
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.

0

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;
}
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;
}
This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.