2012-04-01 17 views
10

Próbuję uruchomić .exe, który wymaga pewnych parametrów przy użyciu system().System C++() nie działa, gdy istnieją spacje w dwóch różnych parametrach

Jeśli istnieje przestrzeń w ścieżce .exe oraz w ścieżce pliku przekazany w parametrach, pojawia się następujący błąd:

The filename, directory name, or volume label syntax is incorrect. 

Oto kod, który generuje ten błąd:

#include <stdlib.h> 
#include <conio.h> 

int main(){ 
    system("\"C:\\Users\\Adam\\Desktop\\pdftotext\" -layout \"C:\\Users\\Adam\\Desktop\\week 4.pdf\""); 
    _getch(); 
} 

Jeśli ścieżka "pdftotext" nie używa cudzysłowów (potrzebuję ich, ponieważ czasami katalog będzie zawierać spacje), wszystko działa poprawnie. Ponadto, jeśli umieściłem to, co jest w "system()" w łańcuchu i wypiszę go i skopiuję w rzeczywistym oknie poleceń, to działa.

Pomyślałem, że może mógłbym łańcuch niektóre polecenia wykorzystujące coś takiego:

cd C:\Users\Adam\Desktop; 
pdftotext -layout "week 4.pdf" 

Więc byłbym już w odpowiednim katalogu, ale nie wiem, jak korzystać z wielu poleceń w tym samym systemie() Funkcja.

Czy ktoś może mi powiedzieć, dlaczego moje polecenie nie działa lub czy drugi sposób, o którym pomyślałem, zadziała?

Edit: Wygląda potrzebowałem dodatkowy zestaw cudzysłowie ponieważ system() przekazuje swoje argumenty do cmd/k, więc to musi być w cudzysłowach. Znalazłem go tutaj:

C++: How to make a my program open a .exe with optional args

więc będę głosować, aby zamknąć jako duplikat, ponieważ pytania są dość blisko, chociaż nie byliśmy dostawanie ten sam komunikat o błędzie, dzięki!

+7

Kto myślał, że wprowadzenie spacji w nazwach będzie „dobry pomysł” powinien zostać zastrzelony. –

+3

Chyba to byłby Microsoft? Wiele rzeczy się zepsuło, gdy praca ludzi zakończyła się na 'C: \ Documents and Settings'. –

+0

Wiem, ale tak naprawdę nie mam wyboru, mam ponad 1000 plików do przeanalizowania i wszystkie mają spacje –

Odpowiedz

21

system() uruchamia polecenie jako cmd /C command. A oto cytat z cmd doc:

If /C or /K is specified, then the remainder of the command line after 
the switch is processed as a command line, where the following logic is 
used to process quote (") characters: 

    1. If all of the following conditions are met, then quote characters 
     on the command line are preserved: 

     - no /S switch 
     - exactly two quote characters 
     - no special characters between the two quote characters, 
      where special is one of: &<>()@^| 
     - there are one or more whitespace characters between the 
      two quote characters 
     - the string between the two quote characters is the name 
      of an executable file. 

    2. Otherwise, old behavior is to see if the first character is 
     a quote character and if so, strip the leading character and 
     remove the last quote character on the command line, preserving 
     any text after the last quote character. 

Wydaje się, że jesteś uderzanie przypadek 2 i cmd uważa, że ​​cały ciąg C:\Users\Adam\Desktop\pdftotext" -layout "C:\Users\Adam\Desktop\week 4.pdf (czyli bez pierwszego i ostatniego cytat) to nazwa pliku wykonywalnego.

Zatem rozwiązaniem byłoby owinąć całą komendę w dodatkowych cytatów:

//system("\"D:\\test\" nospaces \"text with spaces\"");//gives same error as you're getting 
system("\"\"D:\\test\" nospaces \"text with spaces\"\""); //ok, works 

I to jest bardzo dziwne. Myślę, że to również dobry pomysł, aby dodać /S tylko upewnić się, zawsze będzie analizować ciąg przez przypadek 2:

system("cmd /S /C \"\"D:\\test\" nospaces \"text with spaces\"\""); //also works 
+0

@AdamSmith "no/S switch" jest wymagany, aby przypadek 1 miał zastosowanie (patrz dokument), więc zmusza 'cmd' do używania starego zachowania. Nie wspomniano o żadnym innym efekcie. – hamstergene

+0

Dzięki za odpowiedź, działa świetnie! Po przeczytaniu fragmentu opublikowanej dokumentacji masz prawdopodobnie rację, a być może lepiej wykorzystam/S, dziękuję! –