Store filenames in array VC++ - arrays

I am trying to get all the filenames into an array . But after reading all the filenames the array only have the last filename;
#include <Windows.h>
#include <strsafe.h>
#include <iostream>
int main() {
WIN32_FIND_DATA ffd;
HANDLE handle = INVALID_HANDLE_VALUE;
TCHAR *directory = L"D:/*.*";
LPCWSTR filenames[30] ;
handle = FindFirstFile(directory, &ffd);
int count = 0;
if (handle != INVALID_HANDLE_VALUE) {
OutputDebugString(ffd.cFileName);
do {
filenames[count++] = ffd.cFileName;
OutputDebugString(filenames[count -1]);
} while (FindNextFile(handle, &ffd) != 0);
}
else {
OutputDebugString(L"Nothing to display \n");
}
for (int i = 0; i < 10; i++) {
OutputDebugString(filenames[i]);
}
FindClose(handle);
getchar();
return 0;
}
What is the problem I have in this code ..
Thanks in advance..

LPCWSTR filenames[30];
Above is a character array. It is not an array of strings. It is also too short to contain a filename which can be MAX_PATH long.
Use wchar_t **buf; to create an array of strings, or use std::vector and std::string.
If file handle is invalid then do not close it.
Don't use TCHAR unless it is part of some homework or something. Just use wchar_t for Windows.
#include <Windows.h>
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::wstring> vec;
wchar_t *directory = L"D:/*.*";
WIN32_FIND_DATA ffd;
HANDLE handle = FindFirstFile(directory, &ffd);
if (handle != INVALID_HANDLE_VALUE)
{
do {
vec.push_back(ffd.cFileName);
} while (FindNextFile(handle, &ffd));
FindClose(handle);
}
else
{
OutputDebugString(L"Nothing to display \n");
}
for (unsigned int i = 0; i < vec.size(); i++)
{
OutputDebugString(vec[i].c_str());
OutputDebugString(L"\n");
}
getchar();
return 0;
}

Related

How to list only user provided file names from the directory in C?

I know how to printf all files from the directory,but how i find one specific file in that directory using name provided earlier by user?
#include <dirent.h>
#include <stdio.h>
int main(void)
{
DIR *d;
struct dirent *dir;
char a,b;
printf("Path:(eg.c:/): ");
scanf("%s",&a);
d = opendir (&a);
if (d)
{
while ((dir = readdir(d)) != NULL)
{
printf("%s\n", dir->d_name);
}
closedir(d);
}
return(0);
}
From comments:
I would like to know how to implement this in my code because I have never used these functions.
Since you are using Windows, FindFirstFile and FindNextFile can be used to search a directory for a list of filespecs, from there you can simply use strstr to isolate the file you need by comparing the search result with your user's desired filename.
Here is an example that can be modified for your purposes:
#include <stdio.h>
#include <string.h>
#include <windows.h>
void find(char* path,char* file)
{
static int found =0;
HANDLE fh;
WIN32_FIND_DATA wfd;
int i=0;
int j=0;
fh=FindFirstFile(path,&wfd);
if(fh)
{
if(strcmp(wfd.cFileName,file)==0)
{
path[strlen(path)-3]='\0';
strcat(path,file);
FindClose(fh);
return;
}
else
{
while(FindNextFile(fh,&wfd) && found ==0)
{
if(strcmp(wfd.cFileName,file)==0)
{
path[strlen(path)-3]='\0';
strcat(path,file);
FindClose(fh);
found =1;
return;
}
if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
strcmp(wfd.cFileName,"..")!=0 && strcmp(wfd.cFileName,".")!=0)
{
path[strlen(path)-3]='\0';
strcat(path,wfd.cFileName);
strcat(path,"\\*.*");
find(path,file);
}
}
if(found==0)
{
for(i=strlen(path)-1;i>0;i--)
{
if(j==1 && path[i]=='\\')
{
path[i]='\0';
strcat(path,"\\*.*");
break;
}
if(path[i]=='\\')
j=1;
}
}
}
FindClose(fh);
}
}
int main()
{
TCHAR path[512] = "C:\\*.*";
find(path,"notepad.exe");
printf("%s\n",path);
return 0;
}

How to copy multiple files with CopyFile function?

Here is an example my code to copy file from src to dst:
int main() {
const wchar_t* file[3] = { L"\\abc.txt", L"\\def.txt", L"\\ghi.txt" };
for (int i = 0; i < 3; i++) {
wchar_t* src = funcA();
wchar_t* dst = funcB();
wcscat(dst, file[i]);
wcscat(src, file[i]);
CopyFileW(src, dst, TRUE);
}
}
Is there a better way to do that? Can I optimize the code by not running the funcA and funcB many times?
After you fix the errors, your code is copying the file to itself. It boils down to this:
const wchar_t* file[3] = { L"\\abc.txt", L"\\def.txt", L"\\ghi.txt" };
for(int i = 0; i < _countof(file); i++)
CopyFile(file[i], file[i], TRUE);
It's just copying "\\abc.txt" to "\\abc.txt", and "\\def.txt" to "\\def.txt", etc.
Presumably your intention is to copy multiple files from one directory to another directory. For example copy "abc.txt" to "c:\\target\\abc.txt", etc.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main(void)
{
const wchar_t* files[3] = { L"1.txt", L"2.txt", L"3.txt" };
wchar_t *directory = L"c:\\target";
wchar_t dst[MAX_PATH] = { 0 };
for(int i = 0; i < _countof(files); i++)
{
swprintf(dst, _countof(dst), L"%ls\\%ls", directory, files[i]);
CopyFileW(files[i], dst, TRUE);
}
return 0;
}
Note that I changed the source to "abc.txt" and changed the format specifier in swprintf
In a practical application you may want to copy "c:\\src\\1.txt" to "c:\\dst\\1.txt", like this code:
#define UNICODE
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")//Add library (Visual Studio specific)
int main(void)
{
const wchar_t* files[3] =
{ L"c:\\src\\1.txt", L"c:\\src\\2.txt", L"c:\\src\\3.txt" };
wchar_t *directory = L"c:\\dst";
wchar_t dst[MAX_PATH] = { 0 };
if(!PathFileExists(directory))
{
wprintf(L"path error\n");
return 0;
}
for(int i = 0; i < _countof(files); i++)
{
swprintf(dst, _countof(dst), L"%ls\\%ls", directory, PathFindFileName(files[i]));
//CopyFile(files[i], dst, TRUE);
wprintf(L"copy %s to %s\n", files[i], dst);
}
return 0;
}

How to pass value of names in struct array as reference in C?

im supposed to be able to print all of the countries in the printfunction and pass it to the second if statement, but it doesn't seem to be printing . I know it's the
printf("%s\n", ctryList[numCountries].countryName);
part but i don't know what's wrong with it.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
const int MAX_COUNTRY_NAME_LENGTH = 50;
typedef struct CountryTvWatch_struct {
char countryName[50];
int tvMinutes;
} CountryTvWatch;
void PrintCountryNames(CountryTvWatch ctryList[], int numCountries)
{
int i;
for(i = 0; i < numCountries; i++)
{
printf("%s\n", ctryList[numCountries].countryName);
}
return;
}
int main(void) {
// Source: www.statista.com, 2010
const int NUM_COUNTRIES = 4;
CountryTvWatch countryList[NUM_COUNTRIES];
char countryToFind[MAX_COUNTRY_NAME_LENGTH];
bool countryFound = false;
int i = 0;
strcpy(countryList[0].countryName, "Brazil");
countryList[0].tvMinutes = 222;
strcpy(countryList[1].countryName, "India");
countryList[1].tvMinutes = 119;
strcpy(countryList[2].countryName, "U.K.");
countryList[2].tvMinutes = 242;
strcpy(countryList[3].countryName, "U.S.A.");
countryList[3].tvMinutes = 283;
printf("Enter country name: \n");
scanf("%s", countryToFind);
countryFound = false;
for (i = 0; i < NUM_COUNTRIES; ++i) { // Find country's index
if (strcmp(countryList[i].countryName, countryToFind) == 0) {
countryFound = true;
printf("People in %s watch\n", countryToFind);
printf("%d minutes of TV daily.\n", countryList[i].tvMinutes);
}
}
if (!countryFound) {
printf("Country not found, try again.\n");
printf("Valid countries:\n");
PrintCountryNames(countryList, NUM_COUNTRIES);
}
return 0;
}
the following proposed code:
incorporates the comments to the question
properly checks for I/O errors
lets the user know what countries are available to chose from
is appropriately spaced, both horizontally and vertically, for readability
performs the desired functionality
cleanly compiles
documents why each header file is included
and now the proposed code:
#include <stdio.h> // scanf(), printf()
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <string.h> // strcmp()
#include <stdbool.h> // bool, true, false
#define MAX_COUNTRY_NAME_LENGTH 50
#define NUM_COUNTRIES 4
struct CountryTvWatch_struct
{
char countryName[ MAX_COUNTRY_NAME_LENGTH ];
int tvMinutes;
};
typedef struct CountryTvWatch_struct CountryTvWatch;
// prototypes
void PrintCountryNames( CountryTvWatch ctryList[], int numCountries );
int main(void)
{
// Source: www.statista.com, 2010
CountryTvWatch countryList[NUM_COUNTRIES];
char countryToFind[ MAX_COUNTRY_NAME_LENGTH+1];
strcpy(countryList[0].countryName, "Brazil");
countryList[0].tvMinutes = 222;
strcpy(countryList[1].countryName, "India");
countryList[1].tvMinutes = 119;
strcpy(countryList[2].countryName, "U.K.");
countryList[2].tvMinutes = 242;
strcpy(countryList[3].countryName, "U.S.A.");
countryList[3].tvMinutes = 283;
// let user know what countries are available and how they are spelled
PrintCountryNames(countryList, NUM_COUNTRIES);
printf("Enter country name: \n");
// Note: following statement
// checks for error
// includes a MAX_CHAR modifier that is one less than
// the length of the input field
if( 1 != scanf("%49s", countryToFind) )
{
perror( "scanf failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
bool countryFound = false;
for ( int i = 0; i < NUM_COUNTRIES; ++i )
{ // Find country's index
if (strcmp(countryList[i].countryName, countryToFind) == 0)
{
countryFound = true;
printf("People in %s watch\n", countryToFind);
printf("%d minutes of TV daily.\n", countryList[i].tvMinutes);
break; // exit the search loop early
}
}
if (!countryFound)
{
printf("Country not found, try again.\n");
printf("Valid countries:\n");
PrintCountryNames(countryList, NUM_COUNTRIES);
}
return 0;
}
void PrintCountryNames( CountryTvWatch ctryList[], int numCountries )
{
for( int i = 0; i < numCountries; i++ )
{
printf("%s\n", ctryList[ i ].countryName);
}
}

creating multiple recursive directories in c

I am completing cs50x (the edX (free) version of the Harvard cs50) course and am trying to be a bit tricky/lazy/test myself.
I am trying to use a C program to create all the directories I will need for my psets.
I have looked online and found that <sys/stat.h> includes the mkdir() function and therefore tried creating some nested loops to create all the necessary folders by doing something similar to mkdir {pset1,pset1/{standard,hacker},pset2,pset2{standard... to give me a directory structure like this:
pset1/Standard
pset1/Hacker
pset2/Standard
etc...
I came up with this:
#include <cs50.h>
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, string argv[])
{
for(int i = 1; i <=8; i++)
{
string dir = argv[1];
sprintf(dir,"%s%i", argv[1], i);
mkdir(dir, 0777);
for(int j = 0; j<2; j++)
{
string subDir[] = {"Standard","Hacker"};
sprintf(dir,"%s%i/%s", argv[1], i, subDir[j]);
mkdir(dir, 0777);
}
}
}
However, the program only creates pset1 and completes, there are no subfolders, no pset2 etc.
Yes, you're being lazy since you seem to have very little knowledge of C, yet try to program in it. :)
C is not Python, there is no string interpolation/formatting operator. You have to call a function, specificially snprintf(). Read that manual page.
Also, you can't create a bunch of nested directories with a single call to mkdir(). Read the manual page.
To create nested directories, you're either going to have to build each's absolute path (i.e. each successive time you call mkdir() the path will be longer than the previous time), or actually enter each directory as you create it, and go from there.
To create a full path you can call mkdir() recursivly like this:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int mkdirr(const char * path, const mode_t mode, const int fail_on_exist)
{
int result = 0;
char * dir = NULL;
do
{
if (NULL == path)
{
errno = EINVAL;
result = -1;
break;
}
if ((dir = strrchr(path, '/')))
{
*dir = '\0';
result = mkdirr(path, mode, fail_on_exist);
*dir = '/';
if (result)
{
break;
}
}
if (strlen(path))
{
if ((result = mkdir(path, mode)))
{
char s[PATH_MAX];
sprintf(s, "mkdir() failed for '%s'", path);
perror(s);
if ((EEXIST == result) && (0 == fail_on_exist))
{
result = 0;
}
else
{
break;
}
}
}
} while (0);
return result;
}
And then call mkdirr() like this;
int main(void)
{
char p[] = "test/1/2/3";
if (-1 == mkdirr(p, 0777, 0))
{
perror("mkdirr() failed()");
}
return 0;
}

How to use fgetpwent()?

I am trying to get a list of all the users in the system (linux, fedora).
and i've heard that the function:fgetpwent is the one that i need to that mission.
the sad part is that i didnt find any documentation or example of how to use this function.
if someone would give me an example, that would be great, thanks in advance.
No idea why I ever could have used it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crypt.h>
#include <pwd.h>
#include <sys/types.h>
char *testentry = "testread";
static void read_etc_passwd (void) {
struct passwd *pwd_entry = NULL;
int found = 0;
setpwent(); // go to the top of /etc/passwd
while (!found && (pwd_entry = getpwent())){
if (0 == strcmp (testentry, pwd_entry->pw_name)){
found = 1;
}
}
if (found) {
printf ("name = %s\nhome = %s\n", pwd_entry->pw_name,
pwd_entry->pw_dir);
} else {
puts("could not find the entry you were looking for, or"
"some error occurred");
}
}
void change_etc_passwd (void){
struct passwd *pwd = NULL;
FILE *pwd_fd = NULL;
FILE *pwd_new = NULL;
int result = 0;
pwd_fd = fopen ("/etc/passwd", "r");
pwd_new = fopen ("/tmp/passwd.neu", "a");
// assuming everthing went fine (bad idea)
while (pwd = fgetpwent (pwd_fd)){
if (0 == strcmp (pwd->pw_name, testentry)){
pwd->pw_passwd = crypt ("new_pwd", "aa");
}
result = putpwent(pwd, pwd_new);
if (result < 0){
fprintf (stderr, "Failed to write entry, giving up\n");
exit (EXIT_FAILURE);
}
}
}
int main (void) {
/* handling of /etc/passwd */
read_etc_passwd ();
change_etc_passwd();
return 0;
}
Add error handling and it may even work without breaking ;-)

Resources